summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFabian Guerra <fabian.guerra@mapbox.com>2018-04-23 10:44:02 -0400
committerFabian Guerra <fabian.guerra@mapbox.com>2018-04-23 10:44:02 -0400
commite08b6fe87f5824ab05a4cc67d9a76af5bb5ddd3b (patch)
tree886e10260bfa044f62943186ec837b9ccd02934c
parent2bb785dad2489d04db179fa9cf65514640db0a96 (diff)
parenta45670cfb5752866b9c8130024a313944684c2db (diff)
downloadqtlocation-mapboxgl-e08b6fe87f5824ab05a4cc67d9a76af5bb5ddd3b.tar.gz
Merge branch 'release-boba' into masterupstream/fabian-merge-v4.0.0
# Conflicts: # circle.yml # include/mbgl/style/expression/let.hpp # platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java # platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java # platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java # platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java # platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java # platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java # platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java # platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java # platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml # platform/android/gradle/dependencies.gradle # platform/android/src/example_custom_layer.cpp # platform/android/src/geojson/point.cpp # platform/darwin/src/NSPredicate+MGLAdditions.mm # platform/darwin/test/MGLExpressionTests.mm # platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec # platform/ios/Mapbox-iOS-SDK-symbols.podspec # platform/ios/Mapbox-iOS-SDK.podspec # platform/ios/app/MBXViewController.m # src/mbgl/renderer/layers/render_custom_layer.cpp # src/mbgl/style/conversion/filter.cpp # src/mbgl/style/expression/interpolate.cpp # src/mbgl/style/expression/value.cpp # test/style/filter.test.cpp
-rw-r--r--.gitmodules4
-rw-r--r--CMakeLists.txt11
-rw-r--r--Makefile12
-rw-r--r--README.md7
-rw-r--r--bin/offline.cpp4
-rw-r--r--circle.yml84
-rw-r--r--cmake/core-files.cmake3
-rw-r--r--cmake/mbgl.cmake2
-rw-r--r--include/mbgl/renderer/renderer_backend.hpp6
-rw-r--r--include/mbgl/style/conversion/data_driven_property_value.hpp33
-rw-r--r--include/mbgl/style/conversion/expression.hpp39
-rw-r--r--include/mbgl/style/conversion/heatmap_color_property_value.hpp7
-rw-r--r--include/mbgl/style/conversion/property_value.hpp9
-rw-r--r--include/mbgl/style/data_driven_property_value.hpp9
-rw-r--r--include/mbgl/style/expression/length.hpp32
-rw-r--r--include/mbgl/style/expression/let.hpp3
-rw-r--r--include/mbgl/style/expression/literal.hpp4
-rw-r--r--include/mbgl/style/expression/parsing_context.hpp34
-rw-r--r--include/mbgl/style/function/camera_function.hpp11
-rw-r--r--include/mbgl/style/function/composite_function.hpp13
-rw-r--r--include/mbgl/style/function/source_function.hpp15
-rw-r--r--include/mbgl/style/layers/custom_layer.hpp89
-rw-r--r--include/mbgl/util/color.hpp2
m---------mapbox-gl-js0
-rw-r--r--platform/android/MapboxGLAndroidSDK/build.gradle9
-rw-r--r--platform/android/MapboxGLAndroidSDK/gradle.properties3
-rw-r--r--platform/android/MapboxGLAndroidSDK/proguard-rules.pro41
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/AndroidManifest.xml17
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java24
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/attribution/package-info.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/camera/CameraUpdateFactory.java20
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MapboxConstants.java28
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java50
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java42
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngBounds.java33
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/geometry/LatLngSpan.java18
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/http/HTTPRequest.java166
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java7
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapGestureDetector.java286
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapKeyListener.java26
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapView.java88
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMap.java404
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/MapboxMapOptions.java383
-rwxr-xr-xplatform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/NativeMapView.java47
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Projection.java70
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Telemetry.java (renamed from platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Events.java)26
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java419
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Transform.java45
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/UiSettings.java193
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/MapRenderer.java8
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigChooser.java13
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/package-info.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/package-info.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/package-info.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewMapRenderer.java15
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java9
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/package-info.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/CompassView.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java1104
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java389
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineRegion.java84
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/offline/OfflineTilePyramidRegionDefinition.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java9
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/package-info.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java2915
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/package-info.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CameraFunction.java50
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CompositeFunction.java100
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/Function.java300
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/SourceFunction.java85
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/package-info.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/CategoricalStops.java64
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/ExponentialStops.java97
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/IdentityStops.java18
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/IntervalStops.java58
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/IterableStops.java52
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/Stop.java109
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/Stops.java99
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/package-info.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/BackgroundLayer.java3
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CircleLayer.java30
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/CustomLayer.java20
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer.java30
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillLayer.java30
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java230
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/HeatmapLayer.java58
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/HillshadeLayer.java3
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Layer.java13
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/LineLayer.java30
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java1417
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyValue.java41
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/RasterLayer.java3
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/SymbolLayer.java30
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/layer.java.ejs30
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/property_factory.java.ejs70
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Light.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Position.java8
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/GeoJsonSource.java10
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/TileSet.java20
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/VectorSource.java6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/text/package-info.java4
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/utils/MapFragmentUtils.java22
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml6
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values-cs/strings.xml16
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values-he/strings.xml16
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values-pt-rPT/strings.xml16
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values-ru/strings.xml17
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/MapboxTest.java5
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java70
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java19
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java3
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/TrackingSettingsTest.java99
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java148
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettingsTest.java106
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java179
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/layers/FilterTest.java102
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/layers/FunctionTest.java34
-rw-r--r--platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/telemetry/HttpTransportTest.java6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/build.gradle4
-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.java34
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraInternalApiTest.java157
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/MyLocationViewTest.java229
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java236
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/CircleLayerTest.java1602
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ExpressionTest.java207
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java884
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillLayerTest.java837
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HeatmapLayerTest.java590
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HillshadeLayerTest.java438
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java114
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LineLayerTest.java1701
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java473
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/StyleLoaderTest.java77
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/SymbolLayerTest.java5074
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/layer.junit.ejs413
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs60
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml354
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/MapboxApplication.java3
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/FeatureOverviewActivity.java77
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedSymbolLayerActivity.java449
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java20
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/GestureDetectorActivity.java422
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/customlayer/CustomLayerActivity.java6
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QueryRenderedFeaturesBoxHighlightActivity.java11
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QuerySourceFeaturesActivity.java13
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/imagegenerator/SnapshotActivity.java9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/BottomSheetActivity.java12
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/DoubleMapActivity.java19
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/MapPaddingActivity.java27
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java13
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/CircleLayerActivity.java8
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.java159
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionActivity.java39
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/GeoJsonClusteringActivity.java23
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/HeatmapLayerActivity.java16
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/RuntimeStyleActivity.java25
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java151
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java32
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewResizeActivity.java2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewTransparentBackgroundActivity.java (renamed from platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationToggleActivity.java)49
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/BaseLocationActivity.java66
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/CustomLocationEngineActivity.java117
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java130
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java114
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java181
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java296
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/model/activity/Feature.java10
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ResourceUtils.java11
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxxhdpi/water.jpgbin0 -> 165806 bytes
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location_disabled.xml9
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_custom_location_engine.xml27
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_gesture_detector.xml26
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_customization.xml11
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_dot_color.xml62
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_toggle.xml23
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_tracking.xml50
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_textureview_resize.xml2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_textureview_transparent.xml28
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_gesture_alert.xml14
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_gestures.xml12
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_location_engine.xml20
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_padding.xml4
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_tracking.xml32
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/raw/no_bg_style.json43
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml12
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/arrays.xml12
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml7
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/dimens.xml1
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml7
-rw-r--r--platform/android/config.cmake14
-rw-r--r--platform/android/gradle/dependencies.gradle12
-rw-r--r--platform/android/gradle/gradle-javadoc.gradle13
-rw-r--r--platform/android/scripts/exclude-activity-gen.json7
-rwxr-xr-xplatform/android/scripts/generate-style-code.js22
-rw-r--r--platform/android/src/bitmap.cpp10
-rw-r--r--platform/android/src/bitmap.hpp1
-rw-r--r--platform/android/src/example_custom_layer.cpp75
-rw-r--r--platform/android/src/file_source.cpp10
-rw-r--r--platform/android/src/geojson/conversion/feature.hpp2
-rw-r--r--platform/android/src/geojson/conversion/geometry.hpp182
-rw-r--r--platform/android/src/geojson/geometry.cpp47
-rw-r--r--platform/android/src/geojson/geometry.hpp8
-rw-r--r--platform/android/src/geojson/geometry_collection.cpp63
-rw-r--r--platform/android/src/geojson/geometry_collection.hpp28
-rw-r--r--platform/android/src/geojson/line_string.cpp13
-rw-r--r--platform/android/src/geojson/line_string.hpp10
-rw-r--r--platform/android/src/geojson/multi_line_string.cpp11
-rw-r--r--platform/android/src/geojson/multi_line_string.hpp9
-rw-r--r--platform/android/src/geojson/multi_point.cpp10
-rw-r--r--platform/android/src/geojson/multi_point.hpp10
-rw-r--r--platform/android/src/geojson/multi_polygon.cpp23
-rw-r--r--platform/android/src/geojson/multi_polygon.hpp9
-rw-r--r--platform/android/src/geojson/point.cpp7
-rw-r--r--platform/android/src/geojson/point.hpp9
-rw-r--r--platform/android/src/geojson/polygon.cpp10
-rw-r--r--platform/android/src/geojson/polygon.hpp8
-rw-r--r--platform/android/src/geojson/util.hpp38
-rw-r--r--platform/android/src/gson/json_array.cpp19
-rw-r--r--platform/android/src/gson/json_array.hpp2
-rw-r--r--platform/android/src/gson/json_element.cpp28
-rw-r--r--platform/android/src/gson/json_element.hpp2
-rw-r--r--platform/android/src/gson/json_object.cpp17
-rw-r--r--platform/android/src/gson/json_object.hpp2
-rw-r--r--platform/android/src/gson/json_primitive.cpp80
-rw-r--r--platform/android/src/gson/json_primitive.hpp2
-rw-r--r--platform/android/src/http_file_source.cpp2
-rw-r--r--platform/android/src/image.cpp7
-rw-r--r--platform/android/src/java/lang.cpp76
-rw-r--r--platform/android/src/java/lang.hpp50
-rw-r--r--platform/android/src/java/util.cpp2
-rw-r--r--platform/android/src/java/util.hpp15
-rwxr-xr-xplatform/android/src/jni.cpp18
-rw-r--r--platform/android/src/map/image.cpp2
-rw-r--r--platform/android/src/map_renderer.cpp16
-rw-r--r--platform/android/src/map_renderer.hpp5
-rwxr-xr-xplatform/android/src/native_map_view.cpp23
-rwxr-xr-xplatform/android/src/native_map_view.hpp7
-rw-r--r--platform/android/src/offline/offline_manager.cpp8
-rw-r--r--platform/android/src/offline/offline_region.cpp12
-rw-r--r--platform/android/src/snapshotter/map_snapshotter.cpp4
-rw-r--r--platform/android/src/style/conversion/function.hpp208
-rw-r--r--platform/android/src/style/conversion/property_value.hpp19
-rw-r--r--platform/android/src/style/functions/categorical_stops.cpp18
-rw-r--r--platform/android/src/style/functions/categorical_stops.hpp23
-rw-r--r--platform/android/src/style/functions/exponential_stops.cpp18
-rw-r--r--platform/android/src/style/functions/exponential_stops.hpp24
-rw-r--r--platform/android/src/style/functions/identity_stops.cpp18
-rw-r--r--platform/android/src/style/functions/identity_stops.hpp21
-rw-r--r--platform/android/src/style/functions/interval_stops.cpp18
-rw-r--r--platform/android/src/style/functions/interval_stops.hpp23
-rw-r--r--platform/android/src/style/functions/stop.cpp21
-rw-r--r--platform/android/src/style/functions/stop.hpp36
-rw-r--r--platform/android/src/style/layers/custom_layer.cpp10
-rw-r--r--platform/android/src/style/layers/custom_layer.hpp2
-rw-r--r--platform/android/src/style/layers/heatmap_layer.cpp11
-rw-r--r--platform/android/src/style/layers/heatmap_layer.hpp2
-rw-r--r--platform/android/src/style/layers/layer.cpp34
-rw-r--r--platform/android/src/style/layers/layer.cpp.ejs13
-rw-r--r--platform/android/src/style/layers/layer.hpp5
-rw-r--r--platform/android/src/text/local_glyph_rasterizer.cpp1
-rw-r--r--platform/darwin/docs/guides/For Style Authors.md.ejs73
-rw-r--r--platform/darwin/docs/guides/Migrating to Expressions.md.ejs212
-rw-r--r--platform/darwin/docs/guides/Predicates and Expressions.md979
-rw-r--r--platform/darwin/docs/guides/Tile URL Templates.md.ejs14
-rw-r--r--platform/darwin/docs/guides/Using Style Functions at Runtime.md.ejs99
-rw-r--r--platform/darwin/docs/img/data-driven-styling/cast.pngbin0 -> 49974 bytes
-rw-r--r--platform/darwin/docs/img/data-driven-styling/categorical1.pngbin105968 -> 0 bytes
-rw-r--r--platform/darwin/docs/img/data-driven-styling/categorical2.pngbin125698 -> 0 bytes
-rw-r--r--platform/darwin/docs/img/data-driven-styling/citibikes.pngbin152843 -> 0 bytes
-rw-r--r--platform/darwin/docs/img/data-driven-styling/exponential-function-1.pngbin69991 -> 34835 bytes
-rw-r--r--platform/darwin/docs/img/data-driven-styling/exponential-function.pngbin70066 -> 34933 bytes
-rw-r--r--platform/darwin/docs/img/data-driven-styling/exponential.pngbin86910 -> 0 bytes
-rw-r--r--platform/darwin/docs/img/data-driven-styling/identity.pngbin68837 -> 70278 bytes
-rw-r--r--platform/darwin/docs/img/data-driven-styling/interval.pngbin83927 -> 0 bytes
-rw-r--r--platform/darwin/docs/img/data-driven-styling/multiply.pngbin0 -> 50375 bytes
-rw-r--r--platform/darwin/docs/img/data-driven-styling/polylineExample.pngbin156800 -> 0 bytes
-rw-r--r--platform/darwin/docs/theme/assets/css/jazzy.css.scss8
-rw-r--r--platform/darwin/resources/da.lproj/Foundation.strings297
-rw-r--r--platform/darwin/resources/da.lproj/Foundation.stringsdict54
-rw-r--r--platform/darwin/resources/pt-PT.lproj/Foundation.stringsdict54
-rwxr-xr-xplatform/darwin/scripts/generate-style-code.js42
-rw-r--r--platform/darwin/scripts/style-spec-overrides-v8.json22
-rw-r--r--platform/darwin/src/MGLAbstractShapeSource.h124
-rw-r--r--platform/darwin/src/MGLAbstractShapeSource.mm136
-rw-r--r--platform/darwin/src/MGLAccountManager.h26
-rw-r--r--platform/darwin/src/MGLAccountManager.m9
-rw-r--r--platform/darwin/src/MGLAccountManager_Private.h2
-rw-r--r--platform/darwin/src/MGLAttributionInfo.mm7
-rw-r--r--platform/darwin/src/MGLBackgroundStyleLayer.h29
-rw-r--r--platform/darwin/src/MGLBackgroundStyleLayer.mm3
-rw-r--r--platform/darwin/src/MGLCircleStyleLayer.h67
-rw-r--r--platform/darwin/src/MGLComputedShapeSource.h70
-rw-r--r--platform/darwin/src/MGLComputedShapeSource.mm60
-rw-r--r--platform/darwin/src/MGLComputedShapeSource_Private.h (renamed from platform/darwin/src/MGLAbstractShapeSource_Private.h)12
-rw-r--r--platform/darwin/src/MGLFeature.h27
-rw-r--r--platform/darwin/src/MGLFillExtrusionStyleLayer.h45
-rw-r--r--platform/darwin/src/MGLFillExtrusionStyleLayer.mm3
-rw-r--r--platform/darwin/src/MGLFillStyleLayer.h54
-rw-r--r--platform/darwin/src/MGLFillStyleLayer.mm3
-rw-r--r--platform/darwin/src/MGLGeometry.h32
-rw-r--r--platform/darwin/src/MGLGeometry.mm16
-rw-r--r--platform/darwin/src/MGLGeometry_Private.h2
-rw-r--r--platform/darwin/src/MGLHeatmapStyleLayer.h58
-rw-r--r--platform/darwin/src/MGLHillshadeStyleLayer.h77
-rw-r--r--platform/darwin/src/MGLLight.h29
-rw-r--r--platform/darwin/src/MGLLineStyleLayer.h56
-rw-r--r--platform/darwin/src/MGLLineStyleLayer.mm3
-rw-r--r--platform/darwin/src/MGLMapSnapshotter.h2
-rw-r--r--platform/darwin/src/MGLNetworkConfiguration.h2
-rw-r--r--platform/darwin/src/MGLOfflineStorage.h10
-rw-r--r--platform/darwin/src/MGLOfflineStorage.mm4
-rw-r--r--platform/darwin/src/MGLOpenGLStyleLayer.h3
-rw-r--r--platform/darwin/src/MGLOpenGLStyleLayer.mm92
-rw-r--r--platform/darwin/src/MGLPointAnnotation.h5
-rw-r--r--platform/darwin/src/MGLPointCollection.h5
-rw-r--r--platform/darwin/src/MGLPolygon.h9
-rw-r--r--platform/darwin/src/MGLPolyline.h9
-rw-r--r--platform/darwin/src/MGLPolyline.mm8
-rw-r--r--platform/darwin/src/MGLRasterDEMSource.h17
-rw-r--r--platform/darwin/src/MGLRasterDEMSource.mm2
-rw-r--r--platform/darwin/src/MGLRasterStyleLayer.h28
-rw-r--r--platform/darwin/src/MGLRasterTileSource.h (renamed from platform/darwin/src/MGLRasterSource.h)45
-rw-r--r--platform/darwin/src/MGLRasterTileSource.mm (renamed from platform/darwin/src/MGLRasterSource.mm)14
-rw-r--r--platform/darwin/src/MGLRasterTileSource_Private.h (renamed from platform/darwin/src/MGLRasterSource_Private.h)4
-rw-r--r--platform/darwin/src/MGLRendererConfiguration.h2
-rw-r--r--platform/darwin/src/MGLShape.h18
-rw-r--r--platform/darwin/src/MGLShapeCollection.h5
-rw-r--r--platform/darwin/src/MGLShapeSource.h131
-rw-r--r--platform/darwin/src/MGLShapeSource.mm69
-rw-r--r--platform/darwin/src/MGLShapeSource_Private.h4
-rw-r--r--platform/darwin/src/MGLSource.h9
-rw-r--r--platform/darwin/src/MGLStyle.h109
-rw-r--r--platform/darwin/src/MGLStyle.mm182
-rw-r--r--platform/darwin/src/MGLStyleLayer.mm.ejs10
-rw-r--r--platform/darwin/src/MGLStyleValue.h14
-rw-r--r--platform/darwin/src/MGLStyleValue.mm87
-rw-r--r--platform/darwin/src/MGLStyleValue_Private.h8
-rw-r--r--platform/darwin/src/MGLStyle_Private.h4
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.h183
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.mm6
-rw-r--r--platform/darwin/src/MGLTileSource.h6
-rw-r--r--platform/darwin/src/MGLTileSource.mm1
-rw-r--r--platform/darwin/src/MGLVectorStyleLayer.h4
-rw-r--r--platform/darwin/src/MGLVectorTileSource.h (renamed from platform/darwin/src/MGLVectorSource.h)41
-rw-r--r--platform/darwin/src/MGLVectorTileSource.mm (renamed from platform/darwin/src/MGLVectorSource.mm)51
-rw-r--r--platform/darwin/src/MGLVectorTileSource_Private.h (renamed from platform/darwin/src/MGLVectorSource_Private.h)7
-rw-r--r--platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm260
-rw-r--r--platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm60
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.h160
-rw-r--r--platform/darwin/src/NSExpression+MGLAdditions.mm942
-rw-r--r--platform/darwin/src/NSExpression+MGLPrivateAdditions.h10
-rw-r--r--platform/darwin/src/NSPredicate+MGLAdditions.h4
-rw-r--r--platform/darwin/src/NSPredicate+MGLAdditions.mm109
-rw-r--r--platform/darwin/src/NSString+MGLAdditions.m6
-rw-r--r--platform/darwin/src/NSValue+MGLAdditions.h13
-rw-r--r--platform/darwin/src/NSValue+MGLAdditions.m10
-rw-r--r--platform/darwin/test/MGLBackgroundStyleLayerTests.mm18
-rw-r--r--platform/darwin/test/MGLCircleStyleLayerTests.mm112
-rw-r--r--platform/darwin/test/MGLDocumentationExampleTests.swift46
-rw-r--r--platform/darwin/test/MGLDocumentationGuideTests.swift138
-rw-r--r--platform/darwin/test/MGLExpressionTests.mm639
-rw-r--r--platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm64
-rw-r--r--platform/darwin/test/MGLFillStyleLayerTests.mm64
-rw-r--r--platform/darwin/test/MGLGeometryTests.mm9
-rw-r--r--platform/darwin/test/MGLHeatmapColorTests.mm11
-rw-r--r--platform/darwin/test/MGLHeatmapStyleLayerTests.mm40
-rw-r--r--platform/darwin/test/MGLHillshadeStyleLayerTests.mm36
-rw-r--r--platform/darwin/test/MGLLineStyleLayerTests.mm120
-rw-r--r--platform/darwin/test/MGLPredicateTests.mm703
-rw-r--r--platform/darwin/test/MGLRasterStyleLayerTests.mm42
-rw-r--r--platform/darwin/test/MGLSDKTestHelpers.swift17
-rw-r--r--platform/darwin/test/MGLShapeSourceTests.mm1
-rw-r--r--platform/darwin/test/MGLSourceQueryTests.m4
-rw-r--r--platform/darwin/test/MGLStyleLayerTests.mm.ejs20
-rw-r--r--platform/darwin/test/MGLStyleTests.mm154
-rw-r--r--platform/darwin/test/MGLSymbolStyleLayerTests.mm384
-rw-r--r--platform/darwin/test/MGLTileSetTests.mm12
-rw-r--r--platform/default/mbgl/util/default_styles.hpp3
-rw-r--r--platform/ios/CHANGELOG.md75
-rw-r--r--platform/ios/DEVELOPING.md4
-rw-r--r--platform/ios/INSTALL.md2
-rw-r--r--platform/ios/Integration Tests/MBGLIntegrationTests.m215
-rw-r--r--platform/ios/Integration Tests/MGLMapViewIntegrationTest.h20
-rw-r--r--platform/ios/Integration Tests/MGLMapViewIntegrationTest.m79
-rw-r--r--platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec2
-rw-r--r--platform/ios/Mapbox-iOS-SDK-symbols.podspec2
-rw-r--r--platform/ios/Mapbox-iOS-SDK.podspec2
-rw-r--r--platform/ios/Mapbox.playground/Contents.swift117
-rw-r--r--platform/ios/Mapbox.playground/timeline.xctimeline6
-rw-r--r--platform/ios/README.md2
-rw-r--r--platform/ios/app/MBXCustomCalloutView.m4
-rw-r--r--platform/ios/app/MBXViewController.m199
-rw-r--r--platform/ios/app/Main.storyboard60
-rw-r--r--platform/ios/app/da.lproj/Localizable.strings0
-rw-r--r--platform/ios/app/pt-PT.lproj/Localizable.strings0
-rw-r--r--platform/ios/docs/guides/Adding Markers to a Map.md62
-rw-r--r--platform/ios/docs/guides/Adding Points to a Map.md82
-rw-r--r--platform/ios/docs/guides/For Style Authors.md72
-rw-r--r--platform/ios/docs/guides/Info.plist Keys.md2
-rw-r--r--platform/ios/docs/guides/Migrating to Expressions.md266
-rw-r--r--platform/ios/docs/guides/Tile URL Templates.md14
-rw-r--r--platform/ios/docs/guides/Using Style Functions at Runtime.md154
-rw-r--r--platform/ios/docs/img/adding-points-to-a-map/annotation-image.pngbin0 -> 171537 bytes
-rw-r--r--platform/ios/docs/img/adding-points-to-a-map/annotation-view.pngbin0 -> 79919 bytes
-rw-r--r--platform/ios/docs/img/adding-points-to-a-map/circle-layer.pngbin0 -> 215965 bytes
-rw-r--r--platform/ios/docs/img/adding-points-to-a-map/symbol-layer.pngbin0 -> 75743 bytes
-rw-r--r--platform/ios/docs/img/runtime-styling/CustomAnnotations.gifbin45604 -> 44108 bytes
-rw-r--r--platform/ios/docs/img/runtime-styling/DynamicStyles.gifbin97235 -> 94908 bytes
-rw-r--r--platform/ios/docs/img/runtime-styling/Emoji.gifbin177077 -> 126330 bytes
-rw-r--r--platform/ios/docs/img/runtime-styling/HexBins.gifbin554029 -> 435797 bytes
-rw-r--r--platform/ios/docs/img/runtime-styling/Population.gifbin247152 -> 228484 bytes
-rw-r--r--platform/ios/docs/img/runtime-styling/SnowLevels.gifbin489450 -> 463142 bytes
-rw-r--r--platform/ios/docs/img/studio-workflow/add-properties.gifbin239499 -> 176869 bytes
-rw-r--r--platform/ios/docs/img/studio-workflow/create-polygons.gifbin1659146 -> 565786 bytes
-rw-r--r--platform/ios/docs/img/studio-workflow/property-values.pngbin83518 -> 39756 bytes
-rw-r--r--platform/ios/docs/img/studio-workflow/stop-functions.pngbin166947 -> 92170 bytes
-rw-r--r--platform/ios/framework/Settings.bundle/ca.lproj/Root.strings2
-rw-r--r--platform/ios/framework/Settings.bundle/da.lproj/Root.strings3
-rw-r--r--platform/ios/framework/Settings.bundle/de.lproj/Root.strings2
-rw-r--r--platform/ios/framework/Settings.bundle/es.lproj/Root.strings2
-rw-r--r--platform/ios/framework/Settings.bundle/fi.lproj/Root.strings2
-rw-r--r--platform/ios/framework/Settings.bundle/fr.lproj/Root.strings2
-rw-r--r--platform/ios/framework/Settings.bundle/lt.lproj/Root.strings2
-rw-r--r--platform/ios/framework/Settings.bundle/nl.lproj/Root.strings2
-rw-r--r--platform/ios/framework/Settings.bundle/pl.lproj/Root.strings2
-rw-r--r--platform/ios/framework/Settings.bundle/pt-BR.lproj/Root.strings2
-rw-r--r--platform/ios/framework/Settings.bundle/pt-PT.lproj/Root.strings3
-rw-r--r--platform/ios/framework/Settings.bundle/ru.lproj/Root.strings6
-rw-r--r--platform/ios/framework/Settings.bundle/sv.lproj/Root.strings2
-rw-r--r--platform/ios/framework/Settings.bundle/uk.lproj/Root.strings2
-rw-r--r--platform/ios/framework/Settings.bundle/vi.lproj/Root.strings2
-rw-r--r--platform/ios/framework/Settings.bundle/zh-Hans.lproj/Root.strings2
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj589
-rw-r--r--platform/ios/jazzy.yml13
-rw-r--r--platform/ios/resources/api_mapbox_com-digicert_2016.derbin1913 -> 0 bytes
-rw-r--r--platform/ios/resources/api_mapbox_com-digicert_2017.derbin2030 -> 0 bytes
-rw-r--r--platform/ios/resources/api_mapbox_com-geotrust_2016.derbin1757 -> 0 bytes
-rw-r--r--platform/ios/resources/api_mapbox_com-geotrust_2017.derbin1758 -> 0 bytes
-rw-r--r--platform/ios/resources/api_mapbox_staging.derbin1334 -> 0 bytes
-rw-r--r--platform/ios/resources/da.lproj/Localizable.strings117
-rw-r--r--platform/ios/resources/da.lproj/Localizable.stringsdict54
-rw-r--r--platform/ios/resources/pt-PT.lproj/Localizable.stringsbin0 -> 8276 bytes
-rw-r--r--platform/ios/resources/pt-PT.lproj/Localizable.stringsdict54
-rw-r--r--platform/ios/resources/ru.lproj/Localizable.strings58
-rw-r--r--platform/ios/resources/ru.lproj/Localizable.stringsdict50
-rw-r--r--platform/ios/resources/sv.lproj/Localizable.stringsdict38
-rw-r--r--platform/ios/scripts/script_resources/MapboxDemo/MapboxDemo/ViewController.swift2
-rw-r--r--platform/ios/src/MGLAPIClient.h15
-rw-r--r--platform/ios/src/MGLAPIClient.m202
-rw-r--r--platform/ios/src/MGLAnnotationView.h8
-rw-r--r--platform/ios/src/MGLAnnotationView.mm2
-rw-r--r--platform/ios/src/MGLCalloutView.h27
-rw-r--r--platform/ios/src/MGLLocationManager.h25
-rw-r--r--platform/ios/src/MGLLocationManager.m175
-rw-r--r--platform/ios/src/MGLMapAccessibilityElement.mm4
-rw-r--r--platform/ios/src/MGLMapView+IBAdditions.h1
-rw-r--r--platform/ios/src/MGLMapView.h131
-rw-r--r--platform/ios/src/MGLMapView.mm393
-rw-r--r--platform/ios/src/MGLMapboxEvents.h39
-rw-r--r--platform/ios/src/MGLMapboxEvents.m831
-rw-r--r--platform/ios/src/MGLTelemetryConfig.h2
-rw-r--r--platform/ios/src/Mapbox-Prefix.pch1
-rw-r--r--platform/ios/src/Mapbox.h5
-rw-r--r--platform/ios/src/UIColor+MGLAdditions.h7
-rw-r--r--platform/ios/src/UIColor+MGLAdditions.mm49
-rw-r--r--platform/ios/test/MGLAnnotationViewTests.m63
-rw-r--r--platform/ios/test/MGLMapViewLayoutTests.m5
-rw-r--r--platform/ios/test/MGLMapViewScaleBarTests.m62
-rw-r--r--platform/ios/test/MGLNSOrthographyAdditionsTests.m4
-rwxr-xr-xplatform/ios/vendor/SMCalloutView/SMCalloutView.h12
-rwxr-xr-xplatform/ios/vendor/SMCalloutView/SMCalloutView.m43
m---------platform/ios/vendor/mapbox-events-ios0
-rw-r--r--platform/macos/CHANGELOG.md59
-rw-r--r--platform/macos/DEVELOPING.md2
-rw-r--r--platform/macos/Mapbox-macOS-SDK-symbols.podspec2
-rw-r--r--platform/macos/Mapbox-macOS-SDK.podspec2
-rw-r--r--platform/macos/app/Base.lproj/MainMenu.xib28
-rw-r--r--platform/macos/app/Base.lproj/MapDocument.xib17
-rw-r--r--platform/macos/app/MapDocument.m80
-rw-r--r--platform/macos/app/da.lproj/Localizable.strings0
-rw-r--r--platform/macos/app/pt-PT.lproj/Localizable.strings0
-rw-r--r--platform/macos/docs/guides/For Style Authors.md71
-rw-r--r--platform/macos/docs/guides/Info.plist Keys.md2
-rw-r--r--platform/macos/docs/guides/Migrating to Expressions.md267
-rw-r--r--platform/macos/docs/guides/Tile URL Templates.md14
-rw-r--r--platform/macos/docs/guides/Using Style Functions at Runtime.md154
-rw-r--r--platform/macos/docs/img/screenshot.jpgbin351938 -> 411181 bytes
-rw-r--r--platform/macos/jazzy.yml10
-rw-r--r--platform/macos/macos.xcodeproj/project.pbxproj94
-rw-r--r--platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme3
-rw-r--r--platform/macos/sdk/ar.lproj/Localizable.strings27
-rw-r--r--platform/macos/sdk/da.lproj/Localizable.strings27
-rw-r--r--platform/macos/sdk/hu.lproj/Localizable.strings4
-rw-r--r--platform/macos/sdk/pt-PT.lproj/Localizable.strings27
-rw-r--r--platform/macos/sdk/ru.lproj/Localizable.strings6
-rw-r--r--platform/macos/src/MGLMapView.h52
-rw-r--r--platform/macos/src/MGLMapView.mm190
-rw-r--r--platform/macos/src/Mapbox.h5
-rw-r--r--platform/macos/src/NSColor+MGLAdditions.h9
-rw-r--r--platform/macos/src/NSColor+MGLAdditions.mm90
-rw-r--r--platform/node/src/node_expression.cpp4
-rw-r--r--platform/node/src/node_map.cpp28
-rw-r--r--platform/node/src/node_map.hpp1
-rw-r--r--platform/node/test/ignores.json8
-rw-r--r--platform/node/test/js/map.test.js1
-rw-r--r--platform/qt/include/qmapbox.hpp12
-rw-r--r--platform/qt/include/qmapboxgl.hpp5
-rw-r--r--platform/qt/src/qmapbox.cpp22
-rw-r--r--platform/qt/src/qmapboxgl.cpp43
-rw-r--r--src/mbgl/geometry/feature_index.cpp17
-rw-r--r--src/mbgl/geometry/feature_index.hpp7
-rw-r--r--src/mbgl/layout/symbol_instance.cpp4
-rw-r--r--src/mbgl/layout/symbol_layout.cpp4
-rw-r--r--src/mbgl/layout/symbol_projection.cpp6
-rw-r--r--src/mbgl/map/map.cpp1
-rw-r--r--src/mbgl/programs/symbol_program.hpp4
-rw-r--r--src/mbgl/renderer/layers/render_custom_layer.cpp33
-rw-r--r--src/mbgl/renderer/layers/render_custom_layer.hpp3
-rw-r--r--src/mbgl/shaders/collision_box.cpp5
-rw-r--r--src/mbgl/shaders/line_pattern.cpp10
-rw-r--r--src/mbgl/shaders/symbol_icon.cpp7
-rw-r--r--src/mbgl/shaders/symbol_sdf.cpp7
-rw-r--r--src/mbgl/style/conversion/filter.cpp7
-rw-r--r--src/mbgl/style/conversion/stringify.hpp131
-rw-r--r--src/mbgl/style/expression/at.cpp14
-rw-r--r--src/mbgl/style/expression/compound_expression.cpp20
-rw-r--r--src/mbgl/style/expression/interpolate.cpp6
-rw-r--r--src/mbgl/style/expression/length.cpp66
-rw-r--r--src/mbgl/style/expression/parsing_context.cpp72
-rw-r--r--src/mbgl/style/expression/value.cpp9
-rw-r--r--src/mbgl/style/layers/background_layer.cpp2
-rw-r--r--src/mbgl/style/layers/circle_layer.cpp2
-rw-r--r--src/mbgl/style/layers/custom_layer.cpp16
-rw-r--r--src/mbgl/style/layers/custom_layer_impl.cpp12
-rw-r--r--src/mbgl/style/layers/custom_layer_impl.hpp14
-rw-r--r--src/mbgl/style/layers/fill_extrusion_layer.cpp2
-rw-r--r--src/mbgl/style/layers/fill_layer.cpp2
-rw-r--r--src/mbgl/style/layers/heatmap_layer.cpp2
-rw-r--r--src/mbgl/style/layers/hillshade_layer.cpp2
-rw-r--r--src/mbgl/style/layers/layer.cpp.ejs2
-rw-r--r--src/mbgl/style/layers/line_layer.cpp2
-rw-r--r--src/mbgl/style/layers/raster_layer.cpp2
-rw-r--r--src/mbgl/style/layers/symbol_layer.cpp2
-rw-r--r--src/mbgl/tile/geometry_tile.cpp43
-rw-r--r--src/mbgl/tile/geometry_tile.hpp39
-rw-r--r--src/mbgl/tile/geometry_tile_worker.cpp175
-rw-r--r--src/mbgl/tile/geometry_tile_worker.hpp14
-rw-r--r--src/mbgl/util/color.cpp22
-rw-r--r--test/api/custom_layer.test.cpp38
-rw-r--r--test/style/conversion/stringify.test.cpp27
-rw-r--r--test/style/expression/expression.test.cpp2
-rw-r--r--test/style/filter.test.cpp14
-rw-r--r--test/tile/vector_tile.test.cpp33
558 files changed, 17550 insertions, 26988 deletions
diff --git a/.gitmodules b/.gitmodules
index 422fc3930e..e5be61a921 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -7,3 +7,7 @@
[submodule "mapbox-gl-js"]
path = mapbox-gl-js
url = https://github.com/mapbox/mapbox-gl-js.git
+[submodule "platform/ios/vendor/mapbox-events-ios"]
+ path = platform/ios/vendor/mapbox-events-ios
+ url = https://github.com/mapbox/mapbox-events-ios.git
+ branch = boundsj-add-namespace-header
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 181c91df0f..8307191a3f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,6 +7,7 @@ option(WITH_COVERAGE "Enable coverage reports" OFF)
option(WITH_OSMESA "Use OSMesa headless backend" OFF)
option(WITH_EGL "Use EGL backend" OFF)
option(WITH_NODEJS "Download test dependencies like NPM and Node.js" ON)
+option(WITH_ERROR "Add -Werror flag to build (turns warnings into errors)" ON)
include(cmake/mbgl.cmake)
include(cmake/mason.cmake)
@@ -74,8 +75,14 @@ endif(WITH_COVERAGE)
set(CMAKE_CONFIGURATION_TYPES Debug Release RelWithDebugInfo Sanitize)
-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -ftemplate-depth=1024 -fPIC -fvisibility=hidden -Wall -Wextra -Wshadow -Wnon-virtual-dtor -Werror -Wno-variadic-macros -Wno-unknown-pragmas")
-set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -fvisibility=hidden -Wall -Wextra -Wshadow -Werror -Wno-variadic-macros -Wno-unknown-pragmas")
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14 -ftemplate-depth=1024 -fPIC -fvisibility=hidden -Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wno-variadic-macros -Wno-unknown-pragmas")
+set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -fvisibility=hidden -Wall -Wextra -Wshadow -Wno-variadic-macros -Wno-unknown-pragmas")
+
+if (WITH_ERROR)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
+endif()
+
if(APPLE AND CMAKE_CXX_COMPILER_ID MATCHES ".*Clang")
# -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/Makefile b/Makefile
index 818a9585e3..576312cabf 100644
--- a/Makefile
+++ b/Makefile
@@ -45,7 +45,7 @@ ifeq ($(V), 1)
export XCPRETTY
NINJA_ARGS ?= -v
else
- export XCPRETTY ?= | xcpretty
+ export XCPRETTY ?= | tee '$(shell pwd)/build/xcodebuild-$(shell date +"%Y-%m-%d_%H%M%S").log' | xcpretty
NINJA_ARGS ?=
endif
@@ -235,13 +235,17 @@ ios-test: $(IOS_PROJ_PATH)
ios-integration-test: $(IOS_PROJ_PATH)
set -o pipefail && $(IOS_XCODEBUILD_SIM) -scheme 'Integration Test Harness' test $(XCPRETTY)
+.PHONY: ios-sanitize
+ios-sanitize: $(IOS_PROJ_PATH)
+ set -o pipefail && $(IOS_XCODEBUILD_SIM) -scheme 'CI' -enableThreadSanitizer YES -enableUndefinedBehaviorSanitizer YES test $(XCPRETTY)
+
.PHONY: ios-sanitize-address
ios-sanitize-address: $(IOS_PROJ_PATH)
set -o pipefail && $(IOS_XCODEBUILD_SIM) -scheme 'CI' -enableAddressSanitizer YES test $(XCPRETTY)
-.PHONY: ios-sanitize-thread
-ios-sanitize-thread: $(IOS_PROJ_PATH)
- set -o pipefail && $(IOS_XCODEBUILD_SIM) -scheme 'CI' -enableThreadSanitizer YES test $(XCPRETTY)
+.PHONY: ios-static-analyzer
+ios-static-analyzer: $(IOS_PROJ_PATH)
+ set -o pipefail && $(IOS_XCODEBUILD_SIM) analyze -scheme 'CI' test $(XCPRETTY)
.PHONY: ipackage
ipackage: $(IOS_PROJ_PATH)
diff --git a/README.md b/README.md
index 8815e506a7..f5d11bb27e 100644
--- a/README.md
+++ b/README.md
@@ -10,8 +10,8 @@ This repository hosts the cross-platform Mapbox GL Native library, plus convenie
| --------------------------------------- | ---------------------------------- | ---------------------------------------- |
| [Mapbox GL Native](INSTALL.md) | C++14 | [![Circle CI build status](https://circleci.com/gh/mapbox/mapbox-gl-native.svg?style=shield)](https://circleci.com/gh/mapbox/workflows/mapbox-gl-native/tree/master) [![Coverage Status](https://coveralls.io/repos/github/mapbox/mapbox-gl-native/badge.svg?branch=master)](https://coveralls.io/github/mapbox/mapbox-gl-native?branch=master) |
| [Mapbox Maps SDK for Android](platform/android/) | Java | [![Circle CI build status](https://circleci.com/gh/mapbox/mapbox-gl-native.svg?style=shield)](https://circleci.com/gh/mapbox/workflows/mapbox-gl-native/tree/master) |
-| [Mapbox Maps SDK for iOS](platform/ios/) | Objective-C or Swift | [![Bitrise](https://www.bitrise.io/app/7514e4cf3da2cc57.svg?token=OwqZE5rSBR9MVWNr_lf4sA&branch=master)](https://www.bitrise.io/app/7514e4cf3da2cc57) |
-| [Mapbox Maps SDK for macOS](platform/macos/) | Objective-C, Swift, or AppleScript | [![Bitrise](https://www.bitrise.io/app/155ef7da24b38dcd.svg?token=4KSOw_gd6WxTnvGE2rMttg&branch=master)](https://www.bitrise.io/app/155ef7da24b38dcd) |
+| [Mapbox Maps SDK for iOS](platform/ios/) | Objective-C or Swift | [![Circle CI build status](https://circleci.com/gh/mapbox/mapbox-gl-native.svg?style=shield)](https://circleci.com/gh/mapbox/workflows/mapbox-gl-native/tree/master) |
+| [Mapbox Maps SDK for macOS](platform/macos/) | Objective-C, Swift, or AppleScript | [![Circle CI build status](https://circleci.com/gh/mapbox/mapbox-gl-native.svg?style=shield)](https://circleci.com/gh/mapbox/workflows/mapbox-gl-native/tree/master) |
| [node-mapbox-gl-native](platform/node/) | Node.js | [![Circle CI build status](https://circleci.com/gh/mapbox/mapbox-gl-native.svg?style=shield)](https://circleci.com/gh/mapbox/workflows/mapbox-gl-native/tree/master) |
| [Mapbox Maps SDK for Qt](platform/qt) | C++03 | [![Circle CI build status](https://circleci.com/gh/mapbox/mapbox-gl-native.svg?style=shield)](https://circleci.com/gh/mapbox/workflows/mapbox-gl-native/tree/master) [![AppVeyor CI build status](https://ci.appveyor.com/api/projects/status/3q12kbcooc6df8uc?svg=true)](https://ci.appveyor.com/project/Mapbox/mapbox-gl-native) |
@@ -27,4 +27,7 @@ Additional Mapbox GL Native–based libraries for **hybrid applications** are de
If your platform or hybrid application framework isn’t listed here, consider embedding [Mapbox GL JS](https://github.com/mapbox/mapbox-gl-js) using the standard Web capabilities on your platform.
## License
+
+Mapbox GL Native is licensed under the [3-Clause BSD license](LICENSE.md). The licenses of its dependencies are tracked via [FOSSA](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmapbox%2Fmapbox-gl-native):
+
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmapbox%2Fmapbox-gl-native.svg?type=large)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmapbox%2Fmapbox-gl-native)
diff --git a/bin/offline.cpp b/bin/offline.cpp
index 5b403a6416..65396a88fb 100644
--- a/bin/offline.cpp
+++ b/bin/offline.cpp
@@ -21,6 +21,7 @@ int main(int argc, char *argv[]) {
args::ValueFlag<std::string> tokenValue(argumentParser, "key", "Mapbox access token", {'t', "token"});
args::ValueFlag<std::string> styleValue(argumentParser, "URL", "Map stylesheet", {'s', "style"});
args::ValueFlag<std::string> outputValue(argumentParser, "file", "Output database file name", {'o', "output"});
+ args::ValueFlag<std::string> apiBaseValue(argumentParser, "URL", "API Base URL", {'a', "apiBaseURL"});
args::ValueFlag<double> northValue(argumentParser, "degrees", "North latitude", {"north"});
args::ValueFlag<double> westValue(argumentParser, "degrees", "West longitude", {"west"});
@@ -60,6 +61,8 @@ int main(int argc, char *argv[]) {
const char* tokenEnv = getenv("MAPBOX_ACCESS_TOKEN");
const std::string token = tokenValue ? args::get(tokenValue) : (tokenEnv ? tokenEnv : std::string());
+
+ const std::string apiBaseURL = apiBaseValue ? args::get(apiBaseValue) : mbgl::util::API_BASE_URL;
using namespace mbgl;
@@ -68,6 +71,7 @@ int main(int argc, char *argv[]) {
std::unique_ptr<OfflineRegion> region;
fileSource.setAccessToken(token);
+ fileSource.setAPIBaseURL(apiBaseURL);
LatLngBounds boundingBox = LatLngBounds::hull(LatLng(north, west), LatLng(south, east));
OfflineTilePyramidRegionDefinition definition(style, boundingBox, minZoom, maxZoom, pixelRatio);
diff --git a/circle.yml b/circle.yml
index 836f5931dd..5f06791cd6 100644
--- a/circle.yml
+++ b/circle.yml
@@ -32,8 +32,9 @@ workflows:
- linux-gcc5-release-qt4
- linux-gcc5-release-qt5
- ios-debug
- #- ios-sanitize-address
- - ios-sanitize-thread
+ - ios-sanitize
+ - ios-sanitize-address
+ - ios-static-analyzer
- ios-release:
filters:
tags:
@@ -150,8 +151,7 @@ step-library:
run:
name: Install macOS dependencies
command: |
- brew install cmake
- brew install ccache
+ brew install cmake ccache
- &install-macos-node4-dependencies
run:
@@ -171,14 +171,12 @@ step-library:
run:
name: Install macOS Qt dependencies
command: |
- sudo chown -R $USER /usr/local
brew install qt
brew link qt --force
- brew linkapps qt
export HOMEBREW_QT5_CELLAR=$(brew --cellar qt)
export HOMEBREW_QT5_VERSION=$(brew list --versions qt | rev | cut -d' ' -f1 | rev)
- ln -s $HOMEBREW_QT5_CELLAR/$HOMEBREW_QT5_VERSION/mkspecs /usr/local/mkspecs
- ln -s $HOMEBREW_QT5_CELLAR/$HOMEBREW_QT5_VERSION/plugins /usr/local/plugins
+ sudo ln -s $HOMEBREW_QT5_CELLAR/$HOMEBREW_QT5_VERSION/mkspecs /usr/local/mkspecs
+ sudo ln -s $HOMEBREW_QT5_CELLAR/$HOMEBREW_QT5_VERSION/plugins /usr/local/plugins
- &run-node-macos-tests
run:
@@ -223,6 +221,18 @@ step-library:
path: mapbox-gl-js/test/integration/render-tests/index-recycle-map.html
destination: render-tests
+ - &collect-xcode-build-logs
+ run:
+ name: Collect Xcode build logs
+ when: always
+ command: |
+ export XCODE_LOG_DIR=build/logs
+ mkdir -p $XCODE_LOG_DIR
+ cp build/*.log $XCODE_LOG_DIR
+ - &upload-xcode-build-logs
+ store_artifacts:
+ path: build/logs
+
jobs:
nitpick:
docker:
@@ -395,6 +405,9 @@ jobs:
- run:
name: Build package
command: make apackage
+ - run:
+ name: Build release Test App
+ command: make android
- *show-ccache-stats
- *save-cache
- *save-gradle-cache
@@ -409,7 +422,7 @@ jobs:
- deploy:
name: Publish to Maven
command: |
- if [ "${CIRCLE_BRANCH}" == "master" ]; then make run-android-upload-archives ; fi
+ if [ "${CIRCLE_BRANCH}" == "release-boba" ]; then make run-android-upload-archives ; fi
# ------------------------------------------------------------------------------
@@ -706,7 +719,7 @@ jobs:
# ------------------------------------------------------------------------------
ios-debug:
macos:
- xcode: "9.2.0"
+ xcode: "9.3.0"
environment:
BUILDTYPE: Debug
HOMEBREW_NO_AUTO_UPDATE: 1
@@ -727,11 +740,34 @@ jobs:
command: scripts/nitpick/generated-code.js darwin
- *show-ccache-stats
- *save-cache
+ - *collect-xcode-build-logs
+ - *upload-xcode-build-logs
+
+# ------------------------------------------------------------------------------
+ ios-sanitize:
+ macos:
+ xcode: "9.3.0"
+ environment:
+ BUILDTYPE: Debug
+ HOMEBREW_NO_AUTO_UPDATE: 1
+ steps:
+ - checkout
+ - *install-macos-dependencies
+ - *generate-cache-key
+ - *restore-cache
+ - *reset-ccache-stats
+ - run:
+ name: Build and run SDK unit tests with thread and undefined behavior sanitizers
+ command: make ios-sanitize
+ - *show-ccache-stats
+ - *save-cache
+ - *collect-xcode-build-logs
+ - *upload-xcode-build-logs
# ------------------------------------------------------------------------------
ios-sanitize-address:
macos:
- xcode: "9.2.0"
+ xcode: "9.3.0"
environment:
BUILDTYPE: Debug
HOMEBREW_NO_AUTO_UPDATE: 1
@@ -746,11 +782,13 @@ jobs:
command: make ios-sanitize-address
- *show-ccache-stats
- *save-cache
+ - *collect-xcode-build-logs
+ - *upload-xcode-build-logs
# ------------------------------------------------------------------------------
- ios-sanitize-thread:
+ ios-static-analyzer:
macos:
- xcode: "9.2.0"
+ xcode: "9.3.0"
environment:
BUILDTYPE: Debug
HOMEBREW_NO_AUTO_UPDATE: 1
@@ -761,15 +799,17 @@ jobs:
- *restore-cache
- *reset-ccache-stats
- run:
- name: Build and run SDK unit tests with thread sanitizer
- command: make ios-sanitize-thread
+ name: Build and run SDK unit tests with the static analyzer
+ command: make ios-static-analyzer
- *show-ccache-stats
- *save-cache
+ - *collect-xcode-build-logs
+ - *upload-xcode-build-logs
# ------------------------------------------------------------------------------
ios-release:
macos:
- xcode: "9.2.0"
+ xcode: "9.3.0"
environment:
HOMEBREW_NO_AUTO_UPDATE: 1
shell: /bin/bash --login -eo pipefail
@@ -797,7 +837,7 @@ jobs:
# ------------------------------------------------------------------------------
macos-debug:
macos:
- xcode: "9.2.0"
+ xcode: "9.3.0"
environment:
BUILDTYPE: Debug
HOMEBREW_NO_AUTO_UPDATE: 1
@@ -820,6 +860,8 @@ jobs:
- store_artifacts:
path: test/fixtures
destination: test/fixtures
+ - *collect-xcode-build-logs
+ - *upload-xcode-build-logs
# ------------------------------------------------------------------------------
macos-debug-qt5:
@@ -849,7 +891,7 @@ jobs:
# ------------------------------------------------------------------------------
macos-release-node4:
macos:
- xcode: "9.2.0"
+ xcode: "9.3.0"
environment:
BUILDTYPE: RelWithDebInfo
HOMEBREW_NO_AUTO_UPDATE: 1
@@ -866,11 +908,13 @@ jobs:
- *run-node-macos-tests
- *publish-node-package
- *upload-render-tests
+ - *collect-xcode-build-logs
+ - *upload-xcode-build-logs
# ------------------------------------------------------------------------------
macos-release-node6:
macos:
- xcode: "9.2.0"
+ xcode: "9.3.0"
environment:
BUILDTYPE: RelWithDebInfo
HOMEBREW_NO_AUTO_UPDATE: 1
@@ -887,3 +931,5 @@ jobs:
- *run-node-macos-tests
- *publish-node-package
- *upload-render-tests
+ - *collect-xcode-build-logs
+ - *upload-xcode-build-logs
diff --git a/cmake/core-files.cmake b/cmake/core-files.cmake
index 35eb9c9400..0853097630 100644
--- a/cmake/core-files.cmake
+++ b/cmake/core-files.cmake
@@ -410,7 +410,6 @@ set(MBGL_CORE_FILES
include/mbgl/style/conversion/coordinate.hpp
include/mbgl/style/conversion/custom_geometry_source_options.hpp
include/mbgl/style/conversion/data_driven_property_value.hpp
- include/mbgl/style/conversion/expression.hpp
include/mbgl/style/conversion/filter.hpp
include/mbgl/style/conversion/function.hpp
include/mbgl/style/conversion/geojson.hpp
@@ -458,6 +457,7 @@ set(MBGL_CORE_FILES
include/mbgl/style/expression/interpolate.hpp
include/mbgl/style/expression/is_constant.hpp
include/mbgl/style/expression/is_expression.hpp
+ include/mbgl/style/expression/length.hpp
include/mbgl/style/expression/let.hpp
include/mbgl/style/expression/literal.hpp
include/mbgl/style/expression/match.hpp
@@ -480,6 +480,7 @@ set(MBGL_CORE_FILES
src/mbgl/style/expression/interpolate.cpp
src/mbgl/style/expression/is_constant.cpp
src/mbgl/style/expression/is_expression.cpp
+ src/mbgl/style/expression/length.cpp
src/mbgl/style/expression/let.cpp
src/mbgl/style/expression/literal.cpp
src/mbgl/style/expression/match.cpp
diff --git a/cmake/mbgl.cmake b/cmake/mbgl.cmake
index 3d82899538..f087c32511 100644
--- a/cmake/mbgl.cmake
+++ b/cmake/mbgl.cmake
@@ -110,7 +110,7 @@ endfunction()
if(MBGL_PLATFORM STREQUAL "ios")
execute_process(
- COMMAND git submodule update --init platform/ios/vendor/SMCalloutView platform/ios/uitest/KIF platform/ios/uitest/OHHTTPStubs
+ COMMAND git submodule update --init platform/ios/vendor/mapbox-events-ios platform/ios/uitest/KIF platform/ios/uitest/OHHTTPStubs
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}")
endif()
diff --git a/include/mbgl/renderer/renderer_backend.hpp b/include/mbgl/renderer/renderer_backend.hpp
index b83c128169..1d5f4e8f4e 100644
--- a/include/mbgl/renderer/renderer_backend.hpp
+++ b/include/mbgl/renderer/renderer_backend.hpp
@@ -47,10 +47,10 @@ protected:
// as a matched pair, exclusively through BackendScope, in two situations:
//
// 1. When releasing GL resources during Renderer destruction
- // (Including calling CustomLayerDeinitializeFunction during RenderCustomLayer destruction)
+ // (Including calling CustomLayerHost::deinitialize during RenderCustomLayer destruction)
// 2. When renderering through Renderer::render()
- // (Including calling CustomLayerDeinitializeFunction for newly added custom layers and
- // CustomLayerDeinitializeFunction on layer removal)
+ // (Including calling CustomLayerHost::initialize for newly added custom layers and
+ // CustomLayerHost::deinitialize on layer removal)
virtual void activate() = 0;
virtual void deactivate() = 0;
diff --git a/include/mbgl/style/conversion/data_driven_property_value.hpp b/include/mbgl/style/conversion/data_driven_property_value.hpp
index 8880d28fb1..07ed201c99 100644
--- a/include/mbgl/style/conversion/data_driven_property_value.hpp
+++ b/include/mbgl/style/conversion/data_driven_property_value.hpp
@@ -4,10 +4,12 @@
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/function.hpp>
-#include <mbgl/style/conversion/expression.hpp>
#include <mbgl/style/expression/is_expression.hpp>
#include <mbgl/style/expression/is_constant.hpp>
#include <mbgl/style/expression/find_zoom_curve.hpp>
+#include <mbgl/style/expression/literal.hpp>
+#include <mbgl/style/expression/value.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
#include <unordered_set>
@@ -20,24 +22,35 @@ template <class T>
struct Converter<DataDrivenPropertyValue<T>> {
optional<DataDrivenPropertyValue<T>> operator()(const Convertible& value, Error& error) const {
+ using namespace mbgl::style::expression;
+
if (isUndefined(value)) {
return DataDrivenPropertyValue<T>();
- } else if (expression::isExpression(value)) {
- optional<std::unique_ptr<Expression>> expression = convert<std::unique_ptr<Expression>>(
- value,
- error,
- valueTypeToExpressionType<T>());
-
+ } else if (isExpression(value)) {
+ ParsingContext ctx(valueTypeToExpressionType<T>());
+ ParseResult expression = ctx.parseLayerPropertyExpression(value);
if (!expression) {
+ error = { ctx.getCombinedErrors() };
return {};
}
- if (isFeatureConstant(**expression)) {
+ bool featureConstant = isFeatureConstant(**expression);
+ bool zoomConstant = isZoomConstant(**expression);
+
+ if (featureConstant && !zoomConstant) {
return DataDrivenPropertyValue<T>(CameraFunction<T>(std::move(*expression)));
- } else if (isZoomConstant(**expression)) {
+ } else if (!featureConstant && zoomConstant) {
return DataDrivenPropertyValue<T>(SourceFunction<T>(std::move(*expression)));
- } else {
+ } else if (!featureConstant && !zoomConstant) {
return DataDrivenPropertyValue<T>(CompositeFunction<T>(std::move(*expression)));
+ } else {
+ auto literal = dynamic_cast<Literal*>(expression->get());
+ assert(literal);
+ optional<T> constant = fromExpressionValue<T>(literal->getValue());
+ if (!constant) {
+ return {};
+ }
+ return DataDrivenPropertyValue<T>(*constant);
}
} else if (!isObject(value)) {
optional<T> constant = convert<T>(value, error);
diff --git a/include/mbgl/style/conversion/expression.hpp b/include/mbgl/style/conversion/expression.hpp
deleted file mode 100644
index c5fcf906a7..0000000000
--- a/include/mbgl/style/conversion/expression.hpp
+++ /dev/null
@@ -1,39 +0,0 @@
-#pragma once
-
-#include <mbgl/style/expression/parsing_context.hpp>
-#include <mbgl/style/expression/type.hpp>
-#include <mbgl/style/conversion.hpp>
-
-#include <memory>
-
-namespace mbgl {
-namespace style {
-namespace conversion {
-
-using namespace mbgl::style::expression;
-
-template<> struct Converter<std::unique_ptr<Expression>> {
- optional<std::unique_ptr<Expression>> operator()(const Convertible& value, Error& error, type::Type expected) const {
- ParsingContext ctx(optional<type::Type> {expected});
- ParseResult parsed = ctx.parse(value);
- if (parsed) {
- return std::move(*parsed);
- }
- std::string combinedError;
- for (const ParsingError& parsingError : ctx.getErrors()) {
- if (combinedError.size() > 0) {
- combinedError += "\n";
- }
- if (parsingError.key.size() > 0) {
- combinedError += parsingError.key + ": ";
- }
- combinedError += parsingError.message;
- }
- error = { combinedError };
- return {};
- };
-};
-
-} // namespace conversion
-} // namespace style
-} // namespace mbgl
diff --git a/include/mbgl/style/conversion/heatmap_color_property_value.hpp b/include/mbgl/style/conversion/heatmap_color_property_value.hpp
index e3689c524c..a4710792d2 100644
--- a/include/mbgl/style/conversion/heatmap_color_property_value.hpp
+++ b/include/mbgl/style/conversion/heatmap_color_property_value.hpp
@@ -4,11 +4,11 @@
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/function.hpp>
-#include <mbgl/style/conversion/expression.hpp>
#include <mbgl/style/expression/value.hpp>
#include <mbgl/style/expression/is_constant.hpp>
#include <mbgl/style/expression/is_expression.hpp>
#include <mbgl/style/expression/find_zoom_curve.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
namespace mbgl {
namespace style {
@@ -17,11 +17,14 @@ namespace conversion {
template <>
struct Converter<HeatmapColorPropertyValue> {
optional<HeatmapColorPropertyValue> operator()(const Convertible& value, Error& error) const {
+ using namespace mbgl::style::expression;
if (isUndefined(value)) {
return HeatmapColorPropertyValue();
} else if (isExpression(value)) {
- optional<std::unique_ptr<Expression>> expression = convert<std::unique_ptr<Expression>>(value, error, expression::type::Color);
+ ParsingContext ctx(type::Color);
+ ParseResult expression = ctx.parseLayerPropertyExpression(value);
if (!expression) {
+ error = { ctx.getCombinedErrors() };
return {};
}
assert(*expression);
diff --git a/include/mbgl/style/conversion/property_value.hpp b/include/mbgl/style/conversion/property_value.hpp
index 97117de2ec..3130661f61 100644
--- a/include/mbgl/style/conversion/property_value.hpp
+++ b/include/mbgl/style/conversion/property_value.hpp
@@ -4,11 +4,11 @@
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/constant.hpp>
#include <mbgl/style/conversion/function.hpp>
-#include <mbgl/style/conversion/expression.hpp>
#include <mbgl/style/expression/value.hpp>
#include <mbgl/style/expression/is_constant.hpp>
#include <mbgl/style/expression/is_expression.hpp>
#include <mbgl/style/expression/find_zoom_curve.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
namespace mbgl {
namespace style {
@@ -17,13 +17,18 @@ namespace conversion {
template <class T>
struct Converter<PropertyValue<T>> {
optional<PropertyValue<T>> operator()(const Convertible& value, Error& error) const {
+ using namespace mbgl::style::expression;
+
if (isUndefined(value)) {
return PropertyValue<T>();
} else if (isExpression(value)) {
- optional<std::unique_ptr<Expression>> expression = convert<std::unique_ptr<Expression>>(value, error, valueTypeToExpressionType<T>());
+ ParsingContext ctx(valueTypeToExpressionType<T>());
+ ParseResult expression = ctx.parseLayerPropertyExpression(value);
if (!expression) {
+ error = { ctx.getCombinedErrors() };
return {};
}
+
if (isFeatureConstant(**expression)) {
return { CameraFunction<T>(std::move(*expression)) };
} else {
diff --git a/include/mbgl/style/data_driven_property_value.hpp b/include/mbgl/style/data_driven_property_value.hpp
index 5d7c596363..0a1fce29c7 100644
--- a/include/mbgl/style/data_driven_property_value.hpp
+++ b/include/mbgl/style/data_driven_property_value.hpp
@@ -50,6 +50,15 @@ public:
return !value.template is<CameraFunction<T>>() && !value.template is<CompositeFunction<T>>();
}
+ bool isExpression() const {
+ return value.match(
+ [] (const Undefined&) { return false; },
+ [] (const T&) { return false; },
+ [] (const CameraFunction<T>& fn) { return fn.isExpression; },
+ [] (const SourceFunction<T>& fn) { return fn.isExpression; },
+ [] (const CompositeFunction<T>& fn) { return fn.isExpression; });
+ }
+
template <class... Ts>
auto match(Ts&&... ts) const {
return value.match(std::forward<Ts>(ts)...);
diff --git a/include/mbgl/style/expression/length.hpp b/include/mbgl/style/expression/length.hpp
new file mode 100644
index 0000000000..1d754f1932
--- /dev/null
+++ b/include/mbgl/style/expression/length.hpp
@@ -0,0 +1,32 @@
+#pragma once
+
+#include <mbgl/style/expression/expression.hpp>
+#include <mbgl/style/conversion.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
+
+#include <memory>
+#include <vector>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+class Length : public Expression {
+public:
+ Length(std::unique_ptr<Expression> input);
+
+ static ParseResult parse(const mbgl::style::conversion::Convertible& value, ParsingContext& ctx);
+
+ EvaluationResult evaluate(const EvaluationContext& params) const override;
+ void eachChild(const std::function<void(const Expression&)>& visit) const override;
+ bool operator==(const Expression& e) const override;
+ std::vector<optional<Value>> possibleOutputs() const override;
+ std::string getOperator() const override { return "length"; }
+
+private:
+ std::unique_ptr<Expression> input;
+};
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/include/mbgl/style/expression/let.hpp b/include/mbgl/style/expression/let.hpp
index 75d2adda62..d0210d8bba 100644
--- a/include/mbgl/style/expression/let.hpp
+++ b/include/mbgl/style/expression/let.hpp
@@ -70,6 +70,9 @@ public:
mbgl::Value serialize() const override;
std::string getOperator() const override { return "var"; }
+
+ const std::shared_ptr<Expression>& getBoundExpression() const { return value; }
+
private:
std::string name;
std::shared_ptr<Expression> value;
diff --git a/include/mbgl/style/expression/literal.hpp b/include/mbgl/style/expression/literal.hpp
index d854b419f4..a00c468efc 100644
--- a/include/mbgl/style/expression/literal.hpp
+++ b/include/mbgl/style/expression/literal.hpp
@@ -40,6 +40,10 @@ public:
std::vector<optional<Value>> possibleOutputs() const override {
return {{ value }};
}
+
+ Value getValue() const {
+ return value;
+ }
mbgl::Value serialize() const override;
std::string getOperator() const override { return "literal"; }
diff --git a/include/mbgl/style/expression/parsing_context.hpp b/include/mbgl/style/expression/parsing_context.hpp
index f92a4c95ea..c19974a4f7 100644
--- a/include/mbgl/style/expression/parsing_context.hpp
+++ b/include/mbgl/style/expression/parsing_context.hpp
@@ -55,7 +55,7 @@ class ParsingContext {
public:
ParsingContext() : errors(std::make_shared<std::vector<ParsingError>>()) {}
ParsingContext(std::string key_) : key(std::move(key_)), errors(std::make_shared<std::vector<ParsingError>>()) {}
- explicit ParsingContext(optional<type::Type> expected_)
+ explicit ParsingContext(type::Type expected_)
: expected(std::move(expected_)),
errors(std::make_shared<std::vector<ParsingError>>())
{}
@@ -67,6 +67,7 @@ public:
std::string getKey() const { return key; }
optional<type::Type> getExpected() const { return expected; }
const std::vector<ParsingError>& getErrors() const { return *errors; }
+ const std::string getCombinedErrors() const;
enum TypeAnnotationOption {
includeTypeAnnotations,
@@ -74,16 +75,21 @@ public:
};
/*
- Parse the given style-spec JSON value into an Expression object.
- Specifically, this function is responsible for determining the expression
- type (either Literal, or the one named in value[0]) and dispatching to the
- appropriate ParseXxxx::parse(const V&, ParsingContext) method.
+ Parse the given style-spec JSON value as an expression.
*/
- ParseResult parse(const mbgl::style::conversion::Convertible& value,
- TypeAnnotationOption typeAnnotationOption = includeTypeAnnotations);
+ ParseResult parseExpression(const mbgl::style::conversion::Convertible& value,
+ TypeAnnotationOption typeAnnotationOption = includeTypeAnnotations);
/*
- Parse a child expression.
+ Parse the given style-spec JSON value as an expression intended to be used
+ in a layout or paint property. This entails checking additional constraints
+ that exist in that context but not, e.g., for filters.
+ */
+ ParseResult parseLayerPropertyExpression(const mbgl::style::conversion::Convertible& value,
+ TypeAnnotationOption typeAnnotationOption = includeTypeAnnotations);
+
+ /*
+ Parse a child expression. For use by individual Expression::parse() methods.
*/
ParseResult parse(const mbgl::style::conversion::Convertible&,
std::size_t,
@@ -91,7 +97,7 @@ public:
TypeAnnotationOption typeAnnotationOption = includeTypeAnnotations);
/*
- Parse a child expression.
+ Parse a child expression. For use by individual Expression::parse() methods.
*/
ParseResult parse(const mbgl::style::conversion::Convertible&,
std::size_t index,
@@ -141,6 +147,16 @@ private:
errors(std::move(errors_))
{}
+
+ /*
+ Parse the given style-spec JSON value into an Expression object.
+ Specifically, this function is responsible for determining the expression
+ type (either Literal, or the one named in value[0]) and dispatching to the
+ appropriate ParseXxxx::parse(const V&, ParsingContext) method.
+ */
+ ParseResult parse(const mbgl::style::conversion::Convertible& value,
+ TypeAnnotationOption typeAnnotationOption = includeTypeAnnotations);
+
std::string key;
optional<type::Type> expected;
std::shared_ptr<detail::Scope> scope;
diff --git a/include/mbgl/style/function/camera_function.hpp b/include/mbgl/style/function/camera_function.hpp
index 1da5d2c601..97ba633e44 100644
--- a/include/mbgl/style/function/camera_function.hpp
+++ b/include/mbgl/style/function/camera_function.hpp
@@ -27,15 +27,16 @@ public:
IntervalStops<T>>>;
CameraFunction(std::unique_ptr<expression::Expression> expression_)
- : expression(std::move(expression_)),
+ : isExpression(true),
+ expression(std::move(expression_)),
zoomCurve(expression::findZoomCurveChecked(expression.get()))
{
assert(!expression::isZoomConstant(*expression));
assert(expression::isFeatureConstant(*expression));
}
- CameraFunction(Stops stops_)
- : stops(std::move(stops_)),
+ CameraFunction(const Stops& stops)
+ : isExpression(false),
expression(stops.match([&] (const auto& s) {
return expression::Convert::toExpression(s);
})),
@@ -76,12 +77,10 @@ public:
}
bool useIntegerZoom = false;
+ bool isExpression;
const expression::Expression& getExpression() const { return *expression; }
- // retained for compatibility with pre-expression function API
- Stops stops;
-
private:
std::shared_ptr<expression::Expression> expression;
const variant<const expression::InterpolateBase*, const expression::Step*> zoomCurve;
diff --git a/include/mbgl/style/function/composite_function.hpp b/include/mbgl/style/function/composite_function.hpp
index f391b101ae..614c345c25 100644
--- a/include/mbgl/style/function/composite_function.hpp
+++ b/include/mbgl/style/function/composite_function.hpp
@@ -51,16 +51,16 @@ public:
CompositeCategoricalStops<T>>>;
CompositeFunction(std::unique_ptr<expression::Expression> expression_)
- : expression(std::move(expression_)),
+ : isExpression(true),
+ expression(std::move(expression_)),
zoomCurve(expression::findZoomCurveChecked(expression.get()))
{
assert(!expression::isZoomConstant(*expression));
assert(!expression::isFeatureConstant(*expression));
}
- CompositeFunction(std::string property_, Stops stops_, optional<T> defaultValue_ = {})
- : property(std::move(property_)),
- stops(std::move(stops_)),
+ CompositeFunction(const std::string& property, const Stops& stops, optional<T> defaultValue_ = {})
+ : isExpression(false),
defaultValue(std::move(defaultValue_)),
expression(stops.match([&] (const auto& s) {
return expression::Convert::toExpression(property, s);
@@ -113,12 +113,11 @@ public:
const expression::Expression& getExpression() const { return *expression; }
- std::string property;
- Stops stops;
- optional<T> defaultValue;
bool useIntegerZoom = false;
+ bool isExpression;
private:
+ optional<T> defaultValue;
std::shared_ptr<expression::Expression> expression;
const variant<const expression::InterpolateBase*, const expression::Step*> zoomCurve;
};
diff --git a/include/mbgl/style/function/source_function.hpp b/include/mbgl/style/function/source_function.hpp
index d3caa90ee5..5b51d0bf81 100644
--- a/include/mbgl/style/function/source_function.hpp
+++ b/include/mbgl/style/function/source_function.hpp
@@ -30,15 +30,15 @@ public:
IdentityStops<T>>>;
SourceFunction(std::unique_ptr<expression::Expression> expression_)
- : expression(std::move(expression_))
+ : isExpression(true),
+ expression(std::move(expression_))
{
assert(expression::isZoomConstant(*expression));
assert(!expression::isFeatureConstant(*expression));
}
- SourceFunction(std::string property_, Stops stops_, optional<T> defaultValue_ = {})
- : property(std::move(property_)),
- stops(std::move(stops_)),
+ SourceFunction(const std::string& property, const Stops& stops, optional<T> defaultValue_ = {})
+ : isExpression(false),
defaultValue(std::move(defaultValue_)),
expression(stops.match([&] (const IdentityStops<T>&) {
return expression::Convert::fromIdentityFunction(expression::valueTypeToExpressionType<T>(), property);
@@ -67,15 +67,12 @@ public:
}
bool useIntegerZoom = false;
+ bool isExpression;
const expression::Expression& getExpression() const { return *expression; }
- // retained for compatibility with pre-expression function API
- std::string property;
- Stops stops;
- optional<T> defaultValue;
-
private:
+ optional<T> defaultValue;
std::shared_ptr<expression::Expression> expression;
};
diff --git a/include/mbgl/style/layers/custom_layer.hpp b/include/mbgl/style/layers/custom_layer.hpp
index bf3387f95b..fbe3a4a6c2 100644
--- a/include/mbgl/style/layers/custom_layer.hpp
+++ b/include/mbgl/style/layers/custom_layer.hpp
@@ -2,20 +2,13 @@
#include <mbgl/style/layer.hpp>
+#include <array>
+
namespace mbgl {
namespace style {
/**
- * Initialize any GL state needed by the custom layer. This method is called once, from the
- * main thread, at a point when the GL context is active but before rendering for the first
- * time.
- *
- * Resources that are acquired in this method must be released in the UninitializeFunction.
- */
-using CustomLayerInitializeFunction = void (*)(void* context);
-
-/**
- * Parameters that define the current camera position for a CustomLayerRenderFunction.
+ * Parameters that define the current camera position for a `CustomLayerHost::render()` function.
*/
struct CustomLayerRenderParameters {
double width;
@@ -26,48 +19,52 @@ struct CustomLayerRenderParameters {
double bearing;
double pitch;
double fieldOfView;
+ std::array<double, 16> projectionMatrix;
};
-/**
- * Render the layer. This method is called once per frame. The implementation should not make
- * any assumptions about the GL state (other than that the correct context is active). It may
- * make changes to the state, and is not required to reset values such as the depth mask, stencil
- * mask, and corresponding test flags to their original values.
- * Make sure that you are drawing your fragments with a z value of 1 to take advantage of the
- * opaque fragment culling in case there are opaque layers above your custom layer.
- */
-using CustomLayerRenderFunction = void (*)(void* context, const CustomLayerRenderParameters&);
-
-/**
- * Called when the system has destroyed the underlying GL context. The
- * `CustomLayerDeinitializeFunction` will not be called in this case, however
- * `CustomLayerInitializeFunction` will be called instead to prepare for a new render.
- *
- */
-using CustomLayerContextLostFunction = void (*)(void* context);
-
-/**
- * Destroy any GL state needed by the custom layer, and deallocate context, if necessary. This
- * method is called once, from the main thread, at a point when the GL context is active.
- *
- * Note that it may be called even when the InitializeFunction has not been called.
- */
-using CustomLayerDeinitializeFunction = void (*)(void* context);
+class CustomLayerHost {
+public:
+ virtual ~CustomLayerHost() = default;
+ /**
+ * Initialize any GL state needed by the custom layer. This method is called once, from the
+ * main thread, at a point when the GL context is active but before rendering for the first
+ * time.
+ *
+ * Resources that are acquired in this method must be released in the `deinitialize` function.
+ */
+ virtual void initialize() = 0;
+
+ /**
+ * Render the layer. This method is called once per frame. The implementation should not make
+ * any assumptions about the GL state (other than that the correct context is active). It may
+ * make changes to the state, and is not required to reset values such as the depth mask, stencil
+ * mask, and corresponding test flags to their original values.
+ * Make sure that you are drawing your fragments with a z value of 1 to take advantage of the
+ * opaque fragment culling in case there are opaque layers above your custom layer.
+ */
+ virtual void render(const CustomLayerRenderParameters&) = 0;
+
+ /**
+ * Called when the system has destroyed the underlying GL context. The
+ * `deinitialize` function will not be called in this case, however
+ * `initialize` will be called instead to prepare for a new render.
+ *
+ */
+ virtual void contextLost() = 0;
+
+ /**
+ * Destroy any GL state needed by the custom layer, and deallocate context, if necessary. This
+ * method is called once, from the main thread, at a point when the GL context is active.
+ *
+ * Note that it may be called even when the `initialize` function has not been called.
+ */
+ virtual void deinitialize() = 0;
+};
class CustomLayer : public Layer {
public:
CustomLayer(const std::string& id,
- CustomLayerInitializeFunction,
- CustomLayerRenderFunction,
- CustomLayerContextLostFunction,
- CustomLayerDeinitializeFunction,
- void* context);
-
- CustomLayer(const std::string& id,
- CustomLayerInitializeFunction,
- CustomLayerRenderFunction,
- CustomLayerDeinitializeFunction,
- void* context);
+ std::unique_ptr<CustomLayerHost> host);
~CustomLayer() final;
diff --git a/include/mbgl/util/color.hpp b/include/mbgl/util/color.hpp
index 300d7fae82..01a4c8f292 100644
--- a/include/mbgl/util/color.hpp
+++ b/include/mbgl/util/color.hpp
@@ -4,6 +4,7 @@
#include <cassert>
#include <string>
+#include <array>
namespace mbgl {
@@ -37,6 +38,7 @@ public:
static optional<Color> parse(const std::string&);
std::string stringify() const;
+ std::array<double, 4> toArray() const;
};
inline bool operator==(const Color& colorA, const Color& colorB) {
diff --git a/mapbox-gl-js b/mapbox-gl-js
-Subproject 8a19f6079933817fd73eed71159130b8ac53a00
+Subproject 6b96d69ab54b149db1f6ef06daed37379ac0744
diff --git a/platform/android/MapboxGLAndroidSDK/build.gradle b/platform/android/MapboxGLAndroidSDK/build.gradle
index 2bf452e964..c43bc9112b 100644
--- a/platform/android/MapboxGLAndroidSDK/build.gradle
+++ b/platform/android/MapboxGLAndroidSDK/build.gradle
@@ -8,11 +8,6 @@ dependencies {
implementation dependenciesList.supportFragmentV4
implementation dependenciesList.timber
implementation dependenciesList.okhttp3
- compileOnly(dependenciesList.lost) {
- exclude group: 'com.google.guava'
- exclude group: 'com.android.support'
- }
- testImplementation dependenciesList.lost
testImplementation dependenciesList.junit
testImplementation dependenciesList.mockito
testImplementation dependenciesList.robolectric
@@ -111,8 +106,8 @@ android {
}
compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
+ sourceCompatibility JavaVersion.VERSION_1_7
+ targetCompatibility JavaVersion.VERSION_1_7
}
lintOptions {
diff --git a/platform/android/MapboxGLAndroidSDK/gradle.properties b/platform/android/MapboxGLAndroidSDK/gradle.properties
index 3796173fd9..bdfc444454 100644
--- a/platform/android/MapboxGLAndroidSDK/gradle.properties
+++ b/platform/android/MapboxGLAndroidSDK/gradle.properties
@@ -1,5 +1,5 @@
GROUP=com.mapbox.mapboxsdk
-VERSION_NAME=7.0.0-SNAPSHOT
+VERSION_NAME=6.1.0-SNAPSHOT
POM_DESCRIPTION=Mapbox GL Android SDK
POM_URL=https://github.com/mapbox/mapbox-gl-native
@@ -18,4 +18,3 @@ POM_PACKAGING=aar
# Only build native dependencies for the current ABI
# See https://code.google.com/p/android/issues/detail?id=221098#c20
android.buildOnlyTargetAbi=true
-
diff --git a/platform/android/MapboxGLAndroidSDK/proguard-rules.pro b/platform/android/MapboxGLAndroidSDK/proguard-rules.pro
index 3b8adac5a8..83bd7df835 100644
--- a/platform/android/MapboxGLAndroidSDK/proguard-rules.pro
+++ b/platform/android/MapboxGLAndroidSDK/proguard-rules.pro
@@ -2,17 +2,42 @@
# in ../sdk/tools/proguard/proguard-android.txt,
# contents of this file will be appended into proguard-android.txt
-keepattributes Signature, *Annotation*, EnclosingMethod
--keep class almeros.android.multitouch.gesturedetectors.** { *; }
+
+# config for the SDK
-keep class com.mapbox.mapboxsdk.** { *; }
-keep interface com.mapbox.mapboxsdk.** { *; }
--keep class com.mapbox.services.android.telemetry.** { *; }
--keep class com.mapbox.services.commons.** { *;}
--keep class com.google.gson.** { *; }
# config for okhttp 3.8.0, https://github.com/square/okhttp/pull/3354
-dontwarn okio.**
--dontwarn javax.annotation.Nullable
--dontwarn javax.annotation.ParametersAreNonnullByDefault
+-dontwarn javax.annotation.**
+-dontnote okhttp3.**
+
+# config for mapbox-android-telemetry:3.0.0-beta.1
+-keep class com.mapbox.android.telemetry.** { *; }
+-dontwarn com.mapbox.android.core.location.MockLocationEngine
+-dontwarn com.mapbox.android.core.location.MockLocationEngine$LocationUpdateRunnable
+-dontwarn java.awt.Color
+-dontwarn com.mapzen.android.lost.api**
+-dontwarn org.conscrypt.OpenSSLProvider
+-dontwarn org.conscrypt.Conscrypt
+
+# config for mapbox-sdk-geojson:3.0.1
+-keep class com.mapbox.geojson.** { *; }
+-keep class com.google.gson.** { *; }
+-dontnote com.google.gson.internal.UnsafeAllocator
+
+# config for mapbox-android-gestures:0.0.1-20180228.152340-13
+-dontnote com.mapbox.android.gestures.*
-# config for optional location provider https://github.com/mapbox/mapbox-gl-native/issues/10960
--dontwarn com.mapzen.android.lost.api** \ No newline at end of file
+# config for additional warnings
+-keep class com.google.android.gms.dynamite.descriptors.com.google.android.gms.flags.ModuleDescriptor { java.lang.String MODULE_ID; }
+-keep class com.google.android.gms.dynamite.descriptors.com.google.android.gms.flags.ModuleDescriptor { int MODULE_VERSION; }
+-keep class com.google.android.gms.dynamite.DynamiteModule$DynamiteLoaderClassLoader { java.lang.ClassLoader sClassLoader; }
+-dontnote com.google.devtools.build.android.desugar.runtime.ThrowableExtension
+-dontnote org.robolectric.Robolectric
+-dontnote libcore.io.Memory
+-dontnote com.google.protobuf.ExtensionRegistry
+-dontnote com.google.protobuf.Extension
+-dontnote android.net.**
+-dontnote org.apache.http.**
+-dontwarn com.sun.xml.internal.ws.spi.db.** \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDK/src/main/AndroidManifest.xml
index f59585bfe5..dcbec69bfc 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/AndroidManifest.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/AndroidManifest.xml
@@ -1,20 +1,15 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
package="com.mapbox.mapboxsdk">
- <uses-feature android:glEsVersion="0x00020000" android:required="true" />
- <uses-feature android:name="android.hardware.wifi" android:required="false" /> <!-- Implied by ACCESS_WIFI_STATE. -->
- <uses-feature android:name="android.hardware.location.gps" android:required="false"/>
+ <uses-feature
+ android:glEsVersion="0x00020000"
+ android:required="true"/>
+ <uses-feature
+ android:name="android.hardware.wifi"
+ android:required="false"/> <!-- Implied by ACCESS_WIFI_STATE. -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
- <uses-sdk tools:overrideLibrary="com.mapzen.lost"/>
-
- <application>
- <!-- Include the telemetry service to simplify set up (https://www.mapbox.com/telemetry) -->
- <service android:name="com.mapbox.services.android.telemetry.service.TelemetryService"/>
- </application>
-
</manifest>
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
index 853ea1c11b..858c1eed67 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/Mapbox.java
@@ -8,11 +8,9 @@ import android.support.annotation.NonNull;
import android.support.annotation.UiThread;
import android.text.TextUtils;
-import com.mapbox.android.core.location.LocationEngine;
-import com.mapbox.android.core.location.LocationEnginePriority;
-import com.mapbox.android.core.location.LocationEngineProvider;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.exceptions.MapboxConfigurationException;
+import com.mapbox.mapboxsdk.maps.Telemetry;
import com.mapbox.mapboxsdk.net.ConnectivityReceiver;
/**
@@ -31,7 +29,6 @@ public final class Mapbox {
private Context context;
private String accessToken;
private Boolean connected;
- private LocationEngine locationEngine;
/**
* Get an instance of Mapbox.
@@ -47,21 +44,18 @@ public final class Mapbox {
public static synchronized Mapbox getInstance(@NonNull Context context, @NonNull String accessToken) {
if (INSTANCE == null) {
Context appContext = context.getApplicationContext();
- LocationEngineProvider locationEngineProvider = new LocationEngineProvider(context);
- LocationEngine locationEngine = locationEngineProvider.obtainBestLocationEngineAvailable();
- INSTANCE = new Mapbox(appContext, accessToken, locationEngine);
- locationEngine.setPriority(LocationEnginePriority.NO_POWER);
+ INSTANCE = new Mapbox(appContext, accessToken);
+ Telemetry.initialize();
ConnectivityReceiver.instance(appContext);
}
return INSTANCE;
}
- Mapbox(@NonNull Context context, @NonNull String accessToken, LocationEngine locationEngine) {
+ Mapbox(@NonNull Context context, @NonNull String accessToken) {
this.context = context;
this.accessToken = accessToken;
- this.locationEngine = locationEngine;
}
/**
@@ -134,14 +128,4 @@ public final class Mapbox {
NetworkInfo activeNetwork = cm.getActiveNetworkInfo();
return (activeNetwork != null && activeNetwork.isConnected());
}
-
- /**
- * Returns the location engine used by the SDK.
- *
- * @return the location engine configured
- */
- // TODO Do we need to expose this?
- public static LocationEngine getLocationEngine() {
- return INSTANCE.locationEngine;
- }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/attribution/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/attribution/package-info.java
new file mode 100644
index 0000000000..57d840af52
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/attribution/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Contains the Mapbox Maps Android Attribution API classes.
+ */
+package com.mapbox.mapboxsdk.attribution;
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 50e33f4f9f..8ef0d5b523 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
@@ -148,6 +148,26 @@ public final class CameraUpdateFactory {
return new ZoomUpdate(ZoomUpdate.ZOOM_TO, zoom);
}
+ /**
+ * Returns a CameraUpdate that moves the camera viewpoint to a particular bearing.
+ *
+ * @param bearing Bearing to change to
+ * @return CameraUpdate Final Camera Position
+ */
+ public static CameraUpdate bearingTo(double bearing) {
+ return new CameraPositionUpdate(bearing, null, -1, -1);
+ }
+
+ /**
+ * Returns a CameraUpdate that moves the camera viewpoint to a particular tilt.
+ *
+ * @param tilt Tilt to change to
+ * @return CameraUpdate Final Camera Position
+ */
+ public static CameraUpdate tiltTo(double tilt) {
+ return new CameraPositionUpdate(-1, null, tilt, -1);
+ }
+
//
// CameraUpdate types
//
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 6f263e4635..640c70282c 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
@@ -121,23 +121,13 @@ public class MapboxConstants {
public static final String STATE_HAS_SAVED_STATE = "mapbox_savedState";
public static final String STATE_CAMERA_POSITION = "mapbox_cameraPosition";
public static final String STATE_ZOOM_ENABLED = "mapbox_zoomEnabled";
- public static final String STATE_ZOOM_ENABLED_CHANGE = "mapbox_zoomEnabledChange";
public static final String STATE_SCROLL_ENABLED = "mapbox_scrollEnabled";
- public static final String STATE_SCROLL_ENABLED_CHANGE = "mapbox_scrollEnabledChange";
public static final String STATE_ROTATE_ENABLED = "mapbox_rotateEnabled";
- public static final String STATE_ROTATE_ENABLED_CHANGE = "mapbox_rotateEnabledChange";
public static final String STATE_TILT_ENABLED = "mapbox_tiltEnabled";
- public static final String STATE_TILT_ENABLED_CHANGE = "mapbox_tiltEnabledChange";
public static final String STATE_ZOOM_CONTROLS_ENABLED = "mapbox_zoomControlsEnabled";
public static final String STATE_DOUBLE_TAP_ENABLED = "mapbox_doubleTapEnabled";
- public static final String STATE_DOUBLE_TAP_ENABLED_CHANGE = "mapbox_doubleTapEnabledChange";
public static final String STATE_DEBUG_ACTIVE = "mapbox_debugActive";
public static final String STATE_STYLE_URL = "mapbox_styleUrl";
- public static final String STATE_MY_LOCATION_ENABLED = "mapbox_myLocationEnabled";
- public static final String STATE_MY_LOCATION_TRACKING_MODE = "mapbox_myLocationTracking";
- public static final String STATE_MY_BEARING_TRACKING_MODE = "mapbox_myBearingTracking";
- public static final String STATE_MY_LOCATION_TRACKING_DISMISS = "mapbox_myLocationTrackingDismiss";
- public static final String STATE_MY_BEARING_TRACKING_DISMISS = "mapbox_myBearingTrackingDismiss";
public static final String STATE_COMPASS_ENABLED = "mapbox_compassEnabled";
public static final String STATE_COMPASS_GRAVITY = "mapbox_compassGravity";
public static final String STATE_COMPASS_MARGIN_LEFT = "mapbox_compassMarginLeft";
@@ -158,20 +148,12 @@ public class MapboxConstants {
public static final String STATE_ATTRIBUTION_MARGIN_RIGHT = "mapbox_attrMarginRight";
public static final String STATE_ATTRIBUTION_MARGIN_BOTTOM = "mapbox_atrrMarginBottom";
public static final String STATE_ATTRIBUTION_ENABLED = "mapbox_atrrEnabled";
- public static final String STATE_LOCATION_CHANGE_ANIMATION_ENABLED = "mapbox_locationChangeAnimationEnabled";
- public static final String STATE_USING_CUSTOM_LOCATION_SOURCE = "mapbox_usingCustomLocationSource";
- public static final String STATE_LOCATION_VIEW_ENABLED = "mapbox_locViewEnabled";
- public static final String STATE_LOCATION_VIEW_FOREGROUND_DRAWABLE = "mapbox_locViewForegroundDrawable";
- public static final String STATE_LOCATION_VIEW_FOREGROUND_BEARING_DRAWABLE = "mapbox_locViewBearingDrawable";
- public static final String STATE_LOCATION_VIEW_FOREGROUND_TINT_COLOR = "mapbox_locViewForegroundTintColor";
- public static final String STATE_LOCATION_VIEW_BACKGROUND_DRAWABLE = "mapbox_locViewBackgroundDrawable";
- public static final String STATE_LOCATION_VIEW_BACKGROUND_OFFSET = "mapbox_locViewBackgroundOffset";
- public static final String STATE_LOCATION_VIEW_BACKGROUND_TINT_COLOR = "mapbox_locViewBackgroundTintColor";
- public static final String STATE_LOCATION_VIEW_ACCURACY_ALPHA = "mapbox_locViewAccuracyAlpha";
- public static final String STATE_LOCATION_VIEW_ACCURACY_TINT_COLOR = "mapbox_locViewAccuracyTintColor";
- public static final String STATE_LOCATION_VIEW_ACCURACY_THRESHOLD = "mapbox_locViewAccuracyThreshold";
- public static final String STATE_LOCATION_VIEW_PADDING = "mapbox_locViewPadding";
public static final String STATE_DESELECT_MARKER_ON_TAP = "mapbox_deselectMarkerOnTap";
public static final String STATE_USER_FOCAL_POINT = "mapbox_userFocalPoint";
+ public static final String STATE_SCALE_ANIMATION_ENABLED = "mapbox_scaleAnimationEnabled";
+ public static final String STATE_ROTATE_ANIMATION_ENABLED = "mapbox_rotateAnimationEnabled";
+ public static final String STATE_FLING_ANIMATION_ENABLED = "mapbox_flingAnimationEnabled";
+ public static final String STATE_INCREASE_ROTATE_THRESHOLD = "mapbox_increaseRotateThreshold";
+ public static final String STATE_INCREASE_SCALE_THRESHOLD = "mapbox_increaseScaleThreshold";
}
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
deleted file mode 100644
index c042b00577..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyBearingTracking.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.mapbox.mapboxsdk.constants;
-
-import android.support.annotation.IntDef;
-
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * MyBearingTracking exposes different types of bearing tracking modes.
- * <p>
- * These modes visualise the user direction by extracting the direction from either sensor or location data.
- * </p>
- * <p>
- * Required to enable showing the user location first through {@link MapboxMap#setMyLocationEnabled(boolean)}.
- * </p>
- *
- * @see com.mapbox.mapboxsdk.maps.TrackingSettings#setMyBearingTrackingMode(int)
- * @see MyLocationView#setMyBearingTrackingMode(int)
- */
-public class MyBearingTracking {
-
- @IntDef( {NONE, COMPASS, GPS, GPS_NORTH_FACING})
- @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;
-
- /**
- * Tracking the bearing of the user based on GPS data, but camera always faces north direction
- */
- public static final int GPS_NORTH_FACING = 0x0000000B;
-
-}
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
deleted file mode 100644
index 1283283fa5..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/constants/MyLocationTracking.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package com.mapbox.mapboxsdk.constants;
-
-import android.support.annotation.IntDef;
-
-import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.TrackingSettings;
-import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
-
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-
-/**
- * MyLocationTracking exposes types of location tracking modes.
- * * <p>
- * This allows tracking the user location on screen by updating the camera position when a location update occurs.
- * </p>
- * <p>
- * Required to enable showing the user location first through {@link MapboxMap#setMyLocationEnabled(boolean)}.
- * </p>
- *
- * @see MapboxMap#setMyLocationEnabled(boolean)
- * @see TrackingSettings#setMyLocationTrackingMode(int)
- */
-public class MyLocationTracking {
-
- @IntDef( {TRACKING_NONE, TRACKING_FOLLOW})
- @Retention(RetentionPolicy.SOURCE)
- public @interface Mode {
- }
-
- /**
- * Tracking the location of the user 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;
-
-}
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 fc8d2ec8f0..05187cf333 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
@@ -67,7 +67,7 @@ public class LatLngBounds implements Parcelable {
double latCenter = (this.latitudeNorth + this.latitudeSouth) / 2.0;
double longCenter;
- if (this.longitudeEast > this.longitudeWest) {
+ if (this.longitudeEast >= this.longitudeWest) {
longCenter = (this.longitudeEast + this.longitudeWest) / 2;
} else {
double halfSpan = (GeometryConstants.LONGITUDE_SPAN + this.longitudeEast - this.longitudeWest) / 2.0;
@@ -180,7 +180,7 @@ public class LatLngBounds implements Parcelable {
*/
public double getLongitudeSpan() {
double longSpan = Math.abs(this.longitudeEast - this.longitudeWest);
- if (this.longitudeEast > this.longitudeWest) {
+ if (this.longitudeEast >= this.longitudeWest) {
return longSpan;
}
@@ -191,7 +191,7 @@ public class LatLngBounds implements Parcelable {
static double getLongitudeSpan(final double longEast, final double longWest) {
double longSpan = Math.abs(longEast - longWest);
- if (longEast > longWest) {
+ if (longEast >= longWest) {
return longSpan;
}
@@ -283,6 +283,8 @@ public class LatLngBounds implements Parcelable {
* This values of latNorth and latSouth should be in the range of [-90, 90],
* see {@link GeometryConstants#MIN_LATITUDE} and {@link GeometryConstants#MAX_LATITUDE},
* otherwise IllegalArgumentException will be thrown.
+ * latNorth should be greater or equal latSouth, otherwise IllegalArgumentException will be thrown.
+ *
* <p>
* This method doesn't recalculate most east or most west boundaries.
* Note that lonEast and lonWest will be wrapped to be in the range of [-180, 180],
@@ -312,6 +314,10 @@ public class LatLngBounds implements Parcelable {
throw new IllegalArgumentException("latitude must be between -90 and 90");
}
+ if (latNorth < latSouth) {
+ throw new IllegalArgumentException("LatSouth cannot be less than latNorth");
+ }
+
lonEast = LatLng.wrap(lonEast, GeometryConstants.MIN_LONGITUDE, GeometryConstants.MAX_LONGITUDE);
lonWest = LatLng.wrap(lonWest, GeometryConstants.MIN_LONGITUDE, GeometryConstants.MAX_LONGITUDE);
@@ -388,7 +394,7 @@ public class LatLngBounds implements Parcelable {
}
static boolean containsLongitude(final double eastLon, final double westLon, final double longitude) {
- if (eastLon > westLon) {
+ if (eastLon >= westLon) {
return (longitude <= eastLon)
&& (longitude >= westLon);
}
@@ -438,10 +444,21 @@ public class LatLngBounds implements Parcelable {
* @return BoundingBox
*/
public LatLngBounds union(final double latNorth, final double lonEast, final double latSouth, final double lonWest) {
- return new LatLngBounds((this.latitudeNorth < latNorth) ? latNorth : this.latitudeNorth,
- (this.longitudeEast < lonEast) ? lonEast : this.longitudeEast,
- (this.latitudeSouth > latSouth) ? latSouth : this.latitudeSouth,
- (this.longitudeWest > lonWest) ? lonWest : this.longitudeWest);
+ double north = (this.latitudeNorth < latNorth) ? latNorth : this.latitudeNorth;
+ double south = (this.latitudeSouth > latSouth) ? latSouth : this.latitudeSouth;
+
+ if (LatLngSpan.getLongitudeSpan(lonEast, this.longitudeWest)
+ < LatLngSpan.getLongitudeSpan(this.longitudeEast, lonWest)) {
+ return new LatLngBounds(north,
+ lonEast,
+ south,
+ this.longitudeWest);
+ }
+
+ return new LatLngBounds(north,
+ this.longitudeEast,
+ south,
+ lonWest);
}
/**
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 322c7dfb74..133949f743 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
@@ -4,6 +4,8 @@ import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.NonNull;
+import com.mapbox.mapboxsdk.constants.GeometryConstants;
+
/**
* A geographical span defined by its latitude and longitude span.
*/
@@ -136,4 +138,20 @@ public class LatLngSpan implements Parcelable {
result = 31 * result + (int) (temp ^ (temp >>> 32));
return result;
}
+
+ /**
+ * Get the absolute distance, in degrees, between the west and
+ * east boundaries of this LatLngBounds
+ *
+ * @return Span distance
+ */
+ static double getLongitudeSpan(double east, double west) {
+ double longSpan = Math.abs(east - west);
+ if (east > west) {
+ return longSpan;
+ }
+
+ // shortest span contains antimeridian
+ return GeometryConstants.LONGITUDE_SPAN - longSpan;
+ }
}
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 48e3d462ca..d0e51f941f 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
@@ -3,8 +3,11 @@ package com.mapbox.mapboxsdk.http;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.os.Build;
+import android.support.annotation.NonNull;
import android.text.TextUtils;
+import android.util.Log;
+import com.mapbox.android.telemetry.TelemetryUtils;
import com.mapbox.mapboxsdk.BuildConfig;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
@@ -26,54 +29,41 @@ import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
-import okhttp3.internal.Util;
+import okhttp3.ResponseBody;
import timber.log.Timber;
import static android.util.Log.DEBUG;
+import static android.util.Log.ERROR;
import static android.util.Log.INFO;
+import static android.util.Log.VERBOSE;
import static android.util.Log.WARN;
class HTTPRequest implements Callback {
- private static OkHttpClient mClient = new OkHttpClient.Builder().dispatcher(getDispatcher()).build();
- private static boolean logEnabled = true;
- private static boolean logRequestUrl = false;
-
- 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 static Dispatcher getDispatcher() {
- Dispatcher dispatcher = new Dispatcher();
- // Matches core limit set on
- // https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/src/http_file_source.cpp#L192
- dispatcher.setMaxRequestsPerHost(20);
- return dispatcher;
- }
-
- private native void nativeOnFailure(int type, String message);
+ private static OkHttpClient client = new OkHttpClient.Builder().dispatcher(getDispatcher()).build();
+ private static boolean logEnabled = true;
+ private static boolean logRequestUrl = false;
- private native void nativeOnResponse(int code, String etag, String modified, String cacheControl, String expires,
- String retryAfter, String xRateLimitReset, byte[] body);
+ // Reentrancy is not needed, but "Lock" is an abstract class.
+ private ReentrantLock lock = new ReentrantLock();
+ private String userAgentString;
+ private long nativePtr = 0;
+ private Call call;
private HTTPRequest(long nativePtr, String resourceUrl, String etag, String modified) {
- mNativePtr = nativePtr;
+ this.nativePtr = nativePtr;
try {
HttpUrl httpUrl = HttpUrl.parse(resourceUrl);
- final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE);
+ if (httpUrl == null) {
+ log(Log.ERROR, String.format("[HTTP] Unable to parse resourceUrl %s", resourceUrl));
+ }
+ final String host = httpUrl.host().toLowerCase(MapboxConstants.MAPBOX_LOCALE);
// Don't try a request to remote server if we aren't connected
if (!Mapbox.isConnected() && !host.equals("127.0.0.1") && !host.equals("localhost")) {
throw new NoRouteToHostException("No Internet connection available.");
@@ -98,18 +88,18 @@ class HTTPRequest implements Callback {
} else if (modified.length() > 0) {
builder = builder.addHeader("If-Modified-Since", modified);
}
- mRequest = builder.build();
- mCall = mClient.newCall(mRequest);
- mCall.enqueue(this);
+ Request request = builder.build();
+ call = client.newCall(request);
+ call.enqueue(this);
} catch (Exception exception) {
- handleFailure(mCall, exception);
+ handleFailure(call, exception);
}
}
public void cancel() {
- // mCall can be null if the constructor gets aborted (e.g, under a NoRouteToHostException).
- if (mCall != null) {
- mCall.cancel();
+ // call can be null if the constructor gets aborted (e.g, under a NoRouteToHostException).
+ if (call != null) {
+ call.cancel();
}
// TODO: We need a lock here because we can try
@@ -117,37 +107,40 @@ class HTTPRequest implements Callback {
// 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();
+ lock.lock();
+ nativePtr = 0;
+ lock.unlock();
}
@Override
- public void onResponse(Call call, Response response) throws IOException {
+ public void onResponse(@NonNull Call call, @NonNull Response response) throws IOException {
+ if (response.isSuccessful()) {
+ log(VERBOSE, String.format("[HTTP] Request was successful (code = %s).", 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(DEBUG, String.format("[HTTP] Request with response code = %s: %s", response.code(), message));
+ }
- if (logEnabled) {
- if (response.isSuccessful()) {
- Timber.v("[HTTP] Request was successful (code = %s).", 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("[HTTP] Request with response code = %s: %s", response.code(), message);
- }
+ ResponseBody responseBody = response.body();
+ if (responseBody == null) {
+ log(ERROR, "[HTTP] Received empty response body");
+ return;
}
byte[] body;
try {
- body = response.body().bytes();
+ body = responseBody.bytes();
} catch (IOException ioException) {
onFailure(call, ioException);
// throw ioException;
return;
} finally {
- response.body().close();
+ response.close();
}
- mLock.lock();
- if (mNativePtr != 0) {
+ lock.lock();
+ if (nativePtr != 0) {
nativeOnResponse(response.code(),
response.header("ETag"),
response.header("Last-Modified"),
@@ -157,14 +150,34 @@ class HTTPRequest implements Callback {
response.header("x-rate-limit-reset"),
body);
}
- mLock.unlock();
+ lock.unlock();
}
@Override
- public void onFailure(Call call, IOException e) {
+ public void onFailure(@NonNull Call call, @NonNull IOException e) {
handleFailure(call, e);
}
+ static void enableLog(boolean enabled) {
+ logEnabled = enabled;
+ }
+
+ static void enablePrintRequestUrlOnFailure(boolean enabled) {
+ logRequestUrl = enabled;
+ }
+
+ static void setOKHttpClient(OkHttpClient client) {
+ HTTPRequest.client = client;
+ }
+
+ private static Dispatcher getDispatcher() {
+ Dispatcher dispatcher = new Dispatcher();
+ // Matches core limit set on
+ // https://github.com/mapbox/mapbox-gl-native/blob/master/platform/android/src/http_file_source.cpp#L192
+ dispatcher.setMaxRequestsPerHost(20);
+ return dispatcher;
+ }
+
private void handleFailure(Call call, Exception e) {
String errorMessage = e.getMessage() != null ? e.getMessage() : "Error processing the request";
int type = getFailureType(e);
@@ -174,11 +187,11 @@ class HTTPRequest implements Callback {
logFailure(type, errorMessage, requestUrl);
}
- mLock.lock();
- if (mNativePtr != 0) {
+ lock.lock();
+ if (nativePtr != 0) {
nativeOnFailure(type, errorMessage);
}
- mLock.unlock();
+ lock.unlock();
}
private int getFailureType(Exception e) {
@@ -191,19 +204,26 @@ class HTTPRequest implements Callback {
return PERMANENT_ERROR;
}
+ private void log(int type, String errorMessage) {
+ if (logEnabled) {
+ Timber.log(type, errorMessage);
+ }
+ }
+
private void logFailure(int type, String errorMessage, String requestUrl) {
- Timber.log(
- type == TEMPORARY_ERROR ? DEBUG : type == CONNECTION_ERROR ? INFO : WARN,
- "Request failed due to a %s error: %s %s",
- type == TEMPORARY_ERROR ? "temporary" : type == CONNECTION_ERROR ? "connection" : "permanent",
- errorMessage,
- logRequestUrl ? requestUrl : ""
+ log(type == TEMPORARY_ERROR ? DEBUG : type == CONNECTION_ERROR ? INFO : WARN,
+ String.format(
+ "Request failed due to a %s error: %s %s",
+ type == TEMPORARY_ERROR ? "temporary" : type == CONNECTION_ERROR ? "connection" : "permanent",
+ errorMessage,
+ logRequestUrl ? requestUrl : ""
+ )
);
}
private String getUserAgent() {
- if (USER_AGENT_STRING == null) {
- return USER_AGENT_STRING = Util.toHumanReadableAscii(
+ if (userAgentString == null) {
+ userAgentString = TelemetryUtils.toHumanReadableAscii(
String.format("%s %s (%s) Android/%s (%s)",
getApplicationIdentifier(),
BuildConfig.MAPBOX_VERSION_STRING,
@@ -211,9 +231,8 @@ class HTTPRequest implements Callback {
Build.VERSION.SDK_INT,
Build.CPU_ABI)
);
- } else {
- return USER_AGENT_STRING;
}
+ return userAgentString;
}
private String getApplicationIdentifier() {
@@ -226,15 +245,8 @@ class HTTPRequest implements Callback {
}
}
- static void enableLog(boolean enabled) {
- logEnabled = enabled;
- }
-
- static void enablePrintRequestUrlOnFailure(boolean enabled) {
- logRequestUrl = enabled;
- }
+ private native void nativeOnFailure(int type, String message);
- static void setOKHttpClient(OkHttpClient client) {
- mClient = client;
- }
+ private native void nativeOnResponse(int code, String etag, String modified, String cacheControl, String expires,
+ String retryAfter, String xRateLimitReset, byte[] body);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java
index 5ccd6bd795..39cd25631e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/AttributionDialogManager.java
@@ -12,6 +12,7 @@ import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.Toast;
+import com.mapbox.android.telemetry.TelemetryEnabler;
import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.attribution.Attribution;
import com.mapbox.mapboxsdk.attribution.AttributionParser;
@@ -98,7 +99,8 @@ public class AttributionDialogManager implements View.OnClickListener, DialogInt
builder.setPositiveButton(R.string.mapbox_attributionTelemetryPositive, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- Events.obtainTelemetry().enable();
+ TelemetryEnabler.updateTelemetryState(TelemetryEnabler.State.ENABLED);
+ Telemetry.obtainTelemetry().enable();
dialog.cancel();
}
});
@@ -112,7 +114,8 @@ public class AttributionDialogManager implements View.OnClickListener, DialogInt
builder.setNegativeButton(R.string.mapbox_attributionTelemetryNegative, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
- Events.obtainTelemetry().disable();
+ Telemetry.obtainTelemetry().disable();
+ TelemetryEnabler.updateTelemetryState(TelemetryEnabler.State.DISABLED);
dialog.cancel();
}
});
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
index 5f5a10d0d0..de9b4fdbc2 100644
--- 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
@@ -12,6 +12,7 @@ import android.view.MotionEvent;
import android.view.animation.DecelerateInterpolator;
import com.mapbox.android.gestures.AndroidGesturesManager;
+import com.mapbox.android.gestures.Constants;
import com.mapbox.android.gestures.MoveGestureDetector;
import com.mapbox.android.gestures.MultiFingerTapGestureDetector;
import com.mapbox.android.gestures.RotateGestureDetector;
@@ -105,8 +106,40 @@ final class MapGestureDetector {
// Checking for context != null for testing purposes
if (context != null) {
- gesturesManager = new AndroidGesturesManager(context);
+ // Initialize gestures manager
+ AndroidGesturesManager androidGesturesManager = new AndroidGesturesManager(context);
+ initializeGesturesManager(androidGesturesManager, true);
+ // Initialize gesture listeners
+ initializeGestureListeners(context, true);
+ }
+ }
+
+ private void initializeGestureListeners(Context context, boolean attachDefaultListeners) {
+ if (attachDefaultListeners) {
+ StandardGestureListener standardGestureListener = new StandardGestureListener();
+ MoveGestureListener moveGestureListener = new MoveGestureListener();
+ ScaleGestureListener scaleGestureListener = new ScaleGestureListener(
+ context.getResources().getDimension(R.dimen.mapbox_minimum_scale_velocity));
+ RotateGestureListener rotateGestureListener = new RotateGestureListener(
+ context.getResources().getDimension(R.dimen.mapbox_minimum_scale_span_when_rotating),
+ context.getResources().getDimension(R.dimen.mapbox_minimum_angular_velocity),
+ context.getResources().getDimension(R.dimen.mapbox_defaultScaleSpanSinceStartThreshold));
+ ShoveGestureListener shoveGestureListener = new ShoveGestureListener();
+ TapGestureListener tapGestureListener = new TapGestureListener();
+
+ gesturesManager.setStandardGestureListener(standardGestureListener);
+ gesturesManager.setMoveGestureListener(moveGestureListener);
+ gesturesManager.setStandardScaleGestureListener(scaleGestureListener);
+ gesturesManager.setRotateGestureListener(rotateGestureListener);
+ gesturesManager.setShoveGestureListener(shoveGestureListener);
+ gesturesManager.setMultiFingerTapGestureListener(tapGestureListener);
+ }
+ }
+
+ private void initializeGesturesManager(AndroidGesturesManager androidGesturesManager,
+ boolean setDefaultMutuallyExclusives) {
+ if (setDefaultMutuallyExclusives) {
Set<Integer> shoveScaleSet = new HashSet<>();
shoveScaleSet.add(AndroidGesturesManager.GESTURE_TYPE_SHOVE);
shoveScaleSet.add(AndroidGesturesManager.GESTURE_TYPE_SCALE);
@@ -119,20 +152,10 @@ final class MapGestureDetector {
ScaleLongPressSet.add(AndroidGesturesManager.GESTURE_TYPE_SCALE);
ScaleLongPressSet.add(AndroidGesturesManager.GESTURE_TYPE_LONG_PRESS);
- gesturesManager.setMutuallyExclusiveGestures(shoveScaleSet, shoveRotateSet, ScaleLongPressSet);
-
- gesturesManager.setStandardGestureListener(new StandardGestureListener());
- gesturesManager.setMoveGestureListener(new MoveGestureListener());
- gesturesManager.setStandardScaleGestureListener(new ScaleGestureListener(
- context.getResources().getDimension(R.dimen.mapbox_minimum_scale_velocity)
- ));
- gesturesManager.setRotateGestureListener(new RotateGestureListener(
- context.getResources().getDimension(R.dimen.mapbox_minimum_scale_span_when_rotating),
- context.getResources().getDimension(R.dimen.mapbox_minimum_angular_velocity)
- ));
- gesturesManager.setShoveGestureListener(new ShoveGestureListener());
- gesturesManager.setMultiFingerTapGestureListener(new TapGestureListener());
+ androidGesturesManager.setMutuallyExclusiveGestures(shoveScaleSet, shoveRotateSet, ScaleLongPressSet);
}
+
+ gesturesManager = androidGesturesManager;
}
/**
@@ -218,15 +241,17 @@ final class MapGestureDetector {
}
void cancelAnimators() {
- if (scaleAnimator != null) {
- scaleAnimator.cancel();
- }
- if (rotateAnimator != null) {
- rotateAnimator.cancel();
- }
-
animationsTimeoutHandler.removeCallbacksAndMessages(null);
scheduledAnimators.clear();
+
+ cancelAnimator(scaleAnimator);
+ cancelAnimator(rotateAnimator);
+ }
+
+ private void cancelAnimator(Animator animator) {
+ if (animator != null && animator.isStarted()) {
+ animator.cancel();
+ }
}
/**
@@ -319,7 +344,7 @@ final class MapGestureDetector {
notifyOnMapClickListeners(tapPoint);
}
- sendTelemetryEvent(Events.SINGLE_TAP, new PointF(motionEvent.getX(), motionEvent.getY()));
+ sendTelemetryEvent(Telemetry.SINGLE_TAP, new PointF(motionEvent.getX(), motionEvent.getY()));
return true;
}
@@ -338,16 +363,19 @@ final class MapGestureDetector {
transform.cancelTransitions();
cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE);
+ PointF zoomFocalPoint;
// Single finger double tap
if (focalPoint != null) {
// User provided focal point
- transform.zoomIn(focalPoint);
+ zoomFocalPoint = focalPoint;
} else {
// Zoom in on gesture
- transform.zoomIn(new PointF(motionEvent.getX(), motionEvent.getY()));
+ zoomFocalPoint = new PointF(motionEvent.getX(), motionEvent.getY());
}
- sendTelemetryEvent(Events.DOUBLE_TAP, new PointF(motionEvent.getX(), motionEvent.getY()));
+ zoomInAnimated(zoomFocalPoint, false);
+
+ sendTelemetryEvent(Telemetry.DOUBLE_TAP, new PointF(motionEvent.getX(), motionEvent.getY()));
return true;
}
@@ -362,8 +390,14 @@ final class MapGestureDetector {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
- if ((!uiSettings.isScrollGesturesEnabled())) {
- // don't allow a fling is scroll is disabled
+ if (!uiSettings.isScrollGesturesEnabled()) {
+ // don't allow a fling if scroll is disabled
+ return false;
+ }
+
+ notifyOnFlingListeners();
+
+ if (!uiSettings.isFlingVelocityAnimationEnabled()) {
return false;
}
@@ -391,8 +425,6 @@ final class MapGestureDetector {
// update transformation
transform.moveBy(offsetX, offsetY, animationTime);
- notifyOnFlingListeners();
-
return true;
}
}
@@ -407,7 +439,7 @@ final class MapGestureDetector {
transform.cancelTransitions();
cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE);
- sendTelemetryEvent(Events.PAN, detector.getFocalPoint());
+ sendTelemetryEvent(Telemetry.PAN, detector.getFocalPoint());
notifyOnMoveBeginListeners(detector);
@@ -461,16 +493,18 @@ final class MapGestureDetector {
gesturesManager.getMoveGestureDetector().setEnabled(false);
}
- // increase rotate angle threshold when scale is detected first
- gesturesManager.getRotateGestureDetector().setAngleThreshold(
- gesturesManager.getRotateGestureDetector().getDefaultAngleThreshold()
- + MapboxConstants.ROTATION_THRESHOLD_INCREASE_WHEN_SCALING
- );
+ if (uiSettings.isIncreaseRotateThresholdWhenScaling()) {
+ // increase rotate angle threshold when scale is detected first
+ gesturesManager.getRotateGestureDetector().setAngleThreshold(
+ Constants.DEFAULT_ROTATE_ANGLE_THRESHOLD
+ + MapboxConstants.ROTATION_THRESHOLD_INCREASE_WHEN_SCALING
+ );
+ }
// setting focalPoint in #onScaleBegin() as well, because #onScale() might not get called before #onScaleEnd()
setScaleFocalPoint(detector);
- sendTelemetryEvent(Events.PINCH, scaleFocalPoint);
+ sendTelemetryEvent(Telemetry.PINCH, scaleFocalPoint);
notifyOnScaleBeginListeners(detector);
@@ -502,21 +536,27 @@ final class MapGestureDetector {
gesturesManager.getMoveGestureDetector().setEnabled(true);
}
- // resetting default angle threshold
- gesturesManager.getRotateGestureDetector().setAngleThreshold(
- gesturesManager.getRotateGestureDetector().getDefaultAngleThreshold()
- );
+ if (uiSettings.isIncreaseRotateThresholdWhenScaling()) {
+ // resetting default angle threshold
+ gesturesManager.getRotateGestureDetector().setAngleThreshold(
+ Constants.DEFAULT_ROTATE_ANGLE_THRESHOLD
+ );
+ }
+
+ notifyOnScaleEndListeners(detector);
+
+ if (!uiSettings.isScaleVelocityAnimationEnabled()) {
+ return;
+ }
float velocityXY = Math.abs(velocityX) + Math.abs(velocityY);
if (velocityXY > minimumVelocity) {
double zoomAddition = calculateScale(velocityXY, detector.isScalingOut());
double currentZoom = transform.getRawZoom();
long animationTime = (long) (Math.abs(zoomAddition) * 1000 / 4);
- scaleAnimator = createScaleAnimator(currentZoom, zoomAddition, animationTime);
+ scaleAnimator = createScaleAnimator(currentZoom, zoomAddition, scaleFocalPoint, animationTime);
scheduleAnimator(scaleAnimator);
}
-
- notifyOnScaleEndListeners(detector);
}
private void setScaleFocalPoint(StandardScaleGestureDetector detector) {
@@ -540,39 +580,6 @@ final class MapGestureDetector {
return zoomAddition;
}
- private Animator createScaleAnimator(double currentZoom, double zoomAddition, long animationTime) {
- ValueAnimator animator = ValueAnimator.ofFloat((float) currentZoom, (float) (currentZoom + zoomAddition));
- animator.setDuration(animationTime);
- animator.setInterpolator(new DecelerateInterpolator());
- animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- transform.setZoom((Float) animation.getAnimatedValue(), scaleFocalPoint, 0);
- }
- });
-
- animator.addListener(new AnimatorListenerAdapter() {
-
- @Override
- public void onAnimationStart(Animator animation) {
- transform.cancelTransitions();
- cameraChangeDispatcher.onCameraMoveStarted(REASON_API_ANIMATION);
- }
-
- @Override
- public void onAnimationCancel(Animator animation) {
- transform.cancelTransitions();
- }
-
- @Override
- public void onAnimationEnd(Animator animation) {
- cameraChangeDispatcher.onCameraIdle();
- }
- });
- return animator;
- }
-
private double getNewZoom(float scaleFactor, boolean quickZoom) {
double zoomBy = Math.log(scaleFactor) / Math.log(Math.PI / 2);
if (quickZoom) {
@@ -591,10 +598,13 @@ final class MapGestureDetector {
private PointF rotateFocalPoint;
private final float minimumScaleSpanWhenRotating;
private final float minimumAngularVelocity;
+ private final float defaultSpanSinceStartThreshold;
- RotateGestureListener(float minimumScaleSpanWhenRotating, float minimumAngularVelocity) {
+ public RotateGestureListener(float minimumScaleSpanWhenRotating, float minimumAngularVelocity,
+ float defaultSpanSinceStartThreshold) {
this.minimumScaleSpanWhenRotating = minimumScaleSpanWhenRotating;
this.minimumAngularVelocity = minimumAngularVelocity;
+ this.defaultSpanSinceStartThreshold = defaultSpanSinceStartThreshold;
}
@Override
@@ -606,15 +616,17 @@ final class MapGestureDetector {
transform.cancelTransitions();
cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE);
- // when rotation starts, interrupting scale and increasing the threshold
- // to make rotation without scaling easier
- gesturesManager.getStandardScaleGestureDetector().setSpanSinceStartThreshold(minimumScaleSpanWhenRotating);
- gesturesManager.getStandardScaleGestureDetector().interrupt();
+ if (uiSettings.isIncreaseScaleThresholdWhenRotating()) {
+ // when rotation starts, interrupting scale and increasing the threshold
+ // to make rotation without scaling easier
+ gesturesManager.getStandardScaleGestureDetector().setSpanSinceStartThreshold(minimumScaleSpanWhenRotating);
+ gesturesManager.getStandardScaleGestureDetector().interrupt();
+ }
// setting in #onRotateBegin() as well, because #onRotate() might not get called before #onRotateEnd()
setRotateFocalPoint(detector);
- sendTelemetryEvent(Events.ROTATION, rotateFocalPoint);
+ sendTelemetryEvent(Telemetry.ROTATION, rotateFocalPoint);
notifyOnRotateBeginListeners(detector);
@@ -644,9 +656,16 @@ final class MapGestureDetector {
public void onRotateEnd(RotateGestureDetector detector, float velocityX, float velocityY, float angularVelocity) {
cameraChangeDispatcher.onCameraIdle();
- // resetting default scale threshold values
- gesturesManager.getStandardScaleGestureDetector().setSpanSinceStartThreshold(
- gesturesManager.getStandardScaleGestureDetector().getDefaultSpanSinceStartThreshold());
+ if (uiSettings.isIncreaseScaleThresholdWhenRotating()) {
+ // resetting default scale threshold values
+ gesturesManager.getStandardScaleGestureDetector().setSpanSinceStartThreshold(defaultSpanSinceStartThreshold);
+ }
+
+ notifyOnRotateEndListeners(detector);
+
+ if (!uiSettings.isRotateVelocityAnimationEnabled()) {
+ return;
+ }
if (Math.abs(angularVelocity) < minimumAngularVelocity) {
return;
@@ -665,8 +684,6 @@ final class MapGestureDetector {
rotateAnimator = createRotateAnimator(angularVelocity, animationTime);
scheduleAnimator(rotateAnimator);
-
- notifyOnRotateEndListeners(detector);
}
private void setRotateFocalPoint(RotateGestureDetector detector) {
@@ -727,7 +744,7 @@ final class MapGestureDetector {
transform.cancelTransitions();
cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE);
- sendTelemetryEvent(Events.PITCH, detector.getFocalPoint());
+ sendTelemetryEvent(Telemetry.PITCH, detector.getFocalPoint());
// disabling move gesture during shove
gesturesManager.getMoveGestureDetector().setEnabled(false);
@@ -776,23 +793,104 @@ final class MapGestureDetector {
transform.cancelTransitions();
cameraChangeDispatcher.onCameraMoveStarted(REASON_API_GESTURE);
+ sendTelemetryEvent(Telemetry.TWO_FINGER_TAP, detector.getFocalPoint());
+
+ PointF zoomFocalPoint;
+ // Single finger double tap
if (focalPoint != null) {
- transform.zoomOut(focalPoint);
+ // User provided focal point
+ zoomFocalPoint = focalPoint;
} else {
- transform.zoomOut(detector.getFocalPoint());
+ // Zoom in on gesture
+ zoomFocalPoint = detector.getFocalPoint();
}
+ zoomOutAnimated(zoomFocalPoint, false);
+
return true;
}
}
+ private Animator createScaleAnimator(double currentZoom, double zoomAddition, final PointF animationFocalPoint,
+ long animationTime) {
+ ValueAnimator animator = ValueAnimator.ofFloat((float) currentZoom, (float) (currentZoom + zoomAddition));
+ animator.setDuration(animationTime);
+ animator.setInterpolator(new DecelerateInterpolator());
+ animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+
+ @Override
+ public void onAnimationUpdate(ValueAnimator animation) {
+ transform.setZoom((Float) animation.getAnimatedValue(), animationFocalPoint);
+ }
+ });
+
+ animator.addListener(new AnimatorListenerAdapter() {
+
+ @Override
+ public void onAnimationStart(Animator animation) {
+ transform.cancelTransitions();
+ cameraChangeDispatcher.onCameraMoveStarted(REASON_API_ANIMATION);
+ }
+
+ @Override
+ public void onAnimationCancel(Animator animation) {
+ transform.cancelTransitions();
+ }
+
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ cameraChangeDispatcher.onCameraIdle();
+ }
+ });
+ return animator;
+ }
+
+ /**
+ * Zoom in by 1.
+ *
+ * @param zoomFocalPoint focal point of zoom animation
+ * @param runImmediately if true, animation will be started right away, otherwise it will wait until
+ * {@link MotionEvent#ACTION_UP} is registered.
+ */
+ void zoomInAnimated(PointF zoomFocalPoint, boolean runImmediately) {
+ zoomAnimated(true, zoomFocalPoint, runImmediately);
+ }
+
+ /**
+ * Zoom out by 1.
+ *
+ * @param zoomFocalPoint focal point of zoom animation
+ * @param runImmediately if true, animation will be started right away, otherwise it will wait until
+ * {@link MotionEvent#ACTION_UP} is registered.
+ */
+ void zoomOutAnimated(PointF zoomFocalPoint, boolean runImmediately) {
+ zoomAnimated(false, zoomFocalPoint, runImmediately);
+ }
+
+ private void zoomAnimated(boolean zoomIn, PointF zoomFocalPoint, boolean runImmediately) {
+ //canceling here as well, because when using a button it will not be canceled automatically by onDown()
+ cancelAnimator(scaleAnimator);
+
+ double currentZoom = transform.getRawZoom();
+ scaleAnimator = createScaleAnimator(
+ currentZoom,
+ zoomIn ? 1 : -1,
+ zoomFocalPoint,
+ MapboxConstants.ANIMATION_DURATION);
+ if (runImmediately) {
+ scaleAnimator.start();
+ } else {
+ scheduleAnimator(scaleAnimator);
+ }
+ }
+
private void sendTelemetryEvent(String eventType, PointF focalPoint) {
if (isZoomValid(transform)) {
MapEventFactory mapEventFactory = new MapEventFactory();
LatLng latLng = projection.fromScreenLocation(focalPoint);
MapState state = new MapState(latLng.getLatitude(), latLng.getLongitude(), transform.getZoom());
state.setGesture(eventType);
- Events.obtainTelemetry().push(mapEventFactory.createMapGestureEvent(Event.Type.MAP_CLICK, state));
+ Telemetry.obtainTelemetry().push(mapEventFactory.createMapGestureEvent(Event.Type.MAP_CLICK, state));
}
}
@@ -1008,7 +1106,9 @@ final class MapGestureDetector {
return gesturesManager;
}
- void setGesturesManager(AndroidGesturesManager gesturesManager) {
- this.gesturesManager = gesturesManager;
+ void setGesturesManager(Context context, AndroidGesturesManager gesturesManager, boolean attachDefaultListeners,
+ boolean setDefaultMutuallyExclusives) {
+ initializeGesturesManager(gesturesManager, setDefaultMutuallyExclusives);
+ initializeGestureListeners(context, attachDefaultListeners);
}
} \ 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
index 9bd9499fff..08110ff326 100644
--- 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
@@ -13,24 +13,22 @@ import android.view.ViewConfiguration;
* <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 final MapGestureDetector mapGestureDetector;
private TrackballLongPressTimeOut currentTrackballLongPressTimeOut;
- MapKeyListener(@NonNull Transform transform, @NonNull TrackingSettings trackingSettings,
- @NonNull UiSettings uiSettings) {
+ MapKeyListener(Transform transform, UiSettings uiSettings, MapGestureDetector mapGestureDetector) {
this.transform = transform;
- this.trackingSettings = trackingSettings;
this.uiSettings = uiSettings;
+ this.mapGestureDetector = mapGestureDetector;
}
/**
@@ -55,7 +53,7 @@ final class MapKeyListener {
return true;
case KeyEvent.KEYCODE_DPAD_LEFT:
- if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ if (!uiSettings.isScrollGesturesEnabled()) {
return false;
}
@@ -67,7 +65,7 @@ final class MapKeyListener {
return true;
case KeyEvent.KEYCODE_DPAD_RIGHT:
- if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ if (!uiSettings.isScrollGesturesEnabled()) {
return false;
}
@@ -79,7 +77,7 @@ final class MapKeyListener {
return true;
case KeyEvent.KEYCODE_DPAD_UP:
- if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ if (!uiSettings.isScrollGesturesEnabled()) {
return false;
}
@@ -91,7 +89,7 @@ final class MapKeyListener {
return true;
case KeyEvent.KEYCODE_DPAD_DOWN:
- if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ if (!uiSettings.isScrollGesturesEnabled()) {
return false;
}
@@ -128,7 +126,7 @@ final class MapKeyListener {
// Zoom out
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
- transform.zoomOut(focalPoint);
+ mapGestureDetector.zoomOutAnimated(focalPoint, true);
return true;
default:
@@ -164,7 +162,7 @@ final class MapKeyListener {
// Zoom in
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
- transform.zoomIn(focalPoint);
+ mapGestureDetector.zoomInAnimated(focalPoint, true);
return true;
}
@@ -183,7 +181,7 @@ final class MapKeyListener {
switch (event.getActionMasked()) {
// The trackball was rotated
case MotionEvent.ACTION_MOVE:
- if (!trackingSettings.isScrollGestureCurrentlyEnabled()) {
+ if (!uiSettings.isScrollGesturesEnabled()) {
return false;
}
@@ -219,7 +217,7 @@ final class MapKeyListener {
if (currentTrackballLongPressTimeOut != null) {
// Zoom in
PointF focalPoint = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
- transform.zoomIn(focalPoint);
+ mapGestureDetector.zoomInAnimated(focalPoint, true);
}
return true;
@@ -261,7 +259,7 @@ final class MapKeyListener {
if (!cancelled) {
// Zoom out
PointF pointF = new PointF(uiSettings.getWidth() / 2, uiSettings.getHeight() / 2);
- transform.zoomOut(pointF);
+ mapGestureDetector.zoomOutAnimated(pointF, true);
// 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 5a32979b69..22d5dd8f19 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
@@ -38,8 +38,6 @@ import com.mapbox.mapboxsdk.maps.renderer.MapRenderer;
import com.mapbox.mapboxsdk.maps.renderer.glsurfaceview.GLSurfaceViewMapRenderer;
import com.mapbox.mapboxsdk.maps.renderer.textureview.TextureViewMapRenderer;
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.net.ConnectivityReceiver;
import com.mapbox.mapboxsdk.storage.FileSource;
@@ -83,7 +81,6 @@ public class MapView extends FrameLayout {
private boolean destroyed;
private boolean hasSurface;
- private MyLocationView myLocationView;
private CompassView compassView;
private PointF focalPoint;
private ImageView attrView;
@@ -131,7 +128,6 @@ public class MapView extends FrameLayout {
// inflate view
View view = LayoutInflater.from(context).inflate(R.layout.mapbox_mapview_internal, this);
compassView = (CompassView) view.findViewById(R.id.compassView);
- myLocationView = (MyLocationView) view.findViewById(R.id.userLocationView);
attrView = (ImageView) view.findViewById(R.id.attributionView);
logoView = (ImageView) view.findViewById(R.id.logoView);
@@ -153,19 +149,12 @@ public class MapView extends FrameLayout {
// callback for registering touch listeners
GesturesManagerInteractionListener registerTouchListener = new GesturesManagerInteractionListener();
- // callback for zooming in the camera
- CameraZoomInvalidator zoomInvalidator = new CameraZoomInvalidator();
-
// callback for camera change events
final CameraChangeDispatcher cameraChangeDispatcher = new CameraChangeDispatcher();
// setup components for MapboxMap creation
Projection proj = new Projection(nativeMapView);
UiSettings uiSettings = new UiSettings(proj, focalPointInvalidator, compassView, attrView, logoView);
- TrackingSettings trackingSettings = new TrackingSettings(myLocationView, uiSettings, focalPointInvalidator,
- zoomInvalidator);
- MyLocationViewSettings myLocationViewSettings = new MyLocationViewSettings(myLocationView, proj,
- focalPointInvalidator);
LongSparseArray<Annotation> annotationsArray = new LongSparseArray<>();
MarkerViewManager markerViewManager = new MarkerViewManager((ViewGroup) findViewById(R.id.markerViewContainer));
IconManager iconManager = new IconManager(nativeMapView);
@@ -176,30 +165,28 @@ public class MapView extends FrameLayout {
ShapeAnnotations shapeAnnotations = new ShapeAnnotationContainer(nativeMapView, annotationsArray);
AnnotationManager annotationManager = new AnnotationManager(nativeMapView, this, annotationsArray,
markerViewManager, iconManager, annotations, markers, polygons, polylines, shapeAnnotations);
- Transform transform = new Transform(nativeMapView, annotationManager.getMarkerViewManager(), trackingSettings,
+ Transform transform = new Transform(nativeMapView, annotationManager.getMarkerViewManager(),
cameraChangeDispatcher);
- mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, trackingSettings, myLocationViewSettings, proj,
- registerTouchListener, annotationManager, cameraChangeDispatcher);
- focalPointInvalidator.addListener(mapboxMap.createFocalPointChangeListener());
+ mapboxMap = new MapboxMap(nativeMapView, transform, uiSettings, proj, registerTouchListener,
+ annotationManager, cameraChangeDispatcher);
mapCallback.attachMapboxMap(mapboxMap);
// user input
mapGestureDetector = new MapGestureDetector(context, transform, proj, uiSettings,
annotationManager, cameraChangeDispatcher);
- mapKeyListener = new MapKeyListener(transform, trackingSettings, uiSettings);
+ mapKeyListener = new MapKeyListener(transform, uiSettings, mapGestureDetector);
// overlain zoom buttons
mapZoomButtonController = new MapZoomButtonController(new ZoomButtonsController(this));
- MapZoomControllerListener zoomListener = new MapZoomControllerListener(mapGestureDetector, uiSettings, transform,
- cameraChangeDispatcher, getWidth(), getHeight());
+ MapZoomControllerListener zoomListener = new MapZoomControllerListener(
+ mapGestureDetector, cameraChangeDispatcher, getWidth(), getHeight());
mapZoomButtonController.bind(uiSettings, zoomListener);
compassView.injectCompassAnimationListener(createCompassAnimationListener(cameraChangeDispatcher));
compassView.setOnClickListener(createCompassClickListener(cameraChangeDispatcher));
// inject widgets with MapboxMap
- myLocationView.setMapboxMap(mapboxMap);
attrView.setOnClickListener(new AttributionClickListener(context, mapboxMap));
// Ensure this view is interactable
@@ -281,7 +268,7 @@ public class MapView extends FrameLayout {
@UiThread
public void onCreate(@Nullable Bundle savedInstanceState) {
if (savedInstanceState == null) {
- MapboxTelemetry telemetry = Events.obtainTelemetry();
+ MapboxTelemetry telemetry = Telemetry.obtainTelemetry();
AppUserTurnstile turnstileEvent = new AppUserTurnstile(BuildConfig.MAPBOX_SDK_IDENTIFIER,
BuildConfig.MAPBOX_SDK_VERSION);
telemetry.push(turnstileEvent);
@@ -295,7 +282,9 @@ public class MapView extends FrameLayout {
private void initialiseDrawingSurface(MapboxMapOptions options) {
if (options.getTextureMode()) {
TextureView textureView = new TextureView(getContext());
- mapRenderer = new TextureViewMapRenderer(getContext(), textureView, options.getLocalIdeographFontFamily()) {
+ String localFontFamily = options.getLocalIdeographFontFamily();
+ boolean translucentSurface = options.getTranslucentTextureSurface();
+ mapRenderer = new TextureViewMapRenderer(getContext(), textureView, localFontFamily, translucentSurface) {
@Override
protected void onSurfaceCreated(GL10 gl, EGLConfig config) {
MapView.this.onSurfaceCreated();
@@ -324,11 +313,14 @@ public class MapView extends FrameLayout {
private void onSurfaceCreated() {
hasSurface = true;
- post(() -> {
- // Initialise only when not destroyed and only once
- if (!destroyed && mapboxMap == null) {
- initialiseMap();
- mapboxMap.onStart();
+ post(new Runnable() {
+ @Override
+ public void run() {
+ // Initialise only when not destroyed and only once
+ if (!destroyed && mapboxMap == null) {
+ MapView.this.initialiseMap();
+ mapboxMap.onStart();
+ }
}
});
}
@@ -1032,25 +1024,28 @@ public class MapView extends FrameLayout {
}
@Override
- public void setGesturesManager(AndroidGesturesManager gesturesManager) {
- mapGestureDetector.setGesturesManager(gesturesManager);
+ public void setGesturesManager(AndroidGesturesManager gesturesManager, boolean attachDefaultListeners,
+ boolean setDefaultMutuallyExclusives) {
+ mapGestureDetector.setGesturesManager(
+ getContext(), gesturesManager, attachDefaultListeners, setDefaultMutuallyExclusives);
+ }
+
+ @Override
+ public void cancelAllVelocityAnimations() {
+ mapGestureDetector.cancelAnimators();
}
}
private static class MapZoomControllerListener implements ZoomButtonsController.OnZoomListener {
private final MapGestureDetector mapGestureDetector;
- private final UiSettings uiSettings;
- private final Transform transform;
private final CameraChangeDispatcher cameraChangeDispatcher;
private final float mapWidth;
private final float mapHeight;
- MapZoomControllerListener(MapGestureDetector detector, UiSettings uiSettings, Transform transform,
- CameraChangeDispatcher dispatcher, float mapWidth, float mapHeight) {
+ MapZoomControllerListener(MapGestureDetector detector, CameraChangeDispatcher dispatcher,
+ float mapWidth, float mapHeight) {
this.mapGestureDetector = detector;
- this.uiSettings = uiSettings;
- this.transform = transform;
this.cameraChangeDispatcher = dispatcher;
this.mapWidth = mapWidth;
this.mapHeight = mapHeight;
@@ -1074,30 +1069,9 @@ public class MapView extends FrameLayout {
focalPoint = new PointF(mapWidth / 2, mapHeight / 2);
}
if (zoomIn) {
- transform.zoomIn(focalPoint);
- } else {
- transform.zoomOut(focalPoint);
- }
- }
- }
-
- private class CameraZoomInvalidator implements TrackingSettings.CameraZoomInvalidator {
-
- @Override
- public void zoomTo(double zoomLevel) {
- Transform transform = mapboxMap.getTransform();
- double currentZoomLevel = transform.getCameraPosition().zoom;
- if (currentZoomLevel < zoomLevel) {
- setZoom(zoomLevel, mapGestureDetector.getFocalPoint(), transform);
- }
- }
-
- private void setZoom(double zoomLevel, @Nullable PointF focalPoint, @NonNull Transform transform) {
- if (focalPoint != null) {
- transform.setZoom(zoomLevel, focalPoint);
+ mapGestureDetector.zoomInAnimated(focalPoint, true);
} else {
- PointF centerPoint = new PointF(getMeasuredWidth() / 2, getMeasuredHeight() / 2);
- transform.setZoom(zoomLevel, centerPoint);
+ mapGestureDetector.zoomOutAnimated(focalPoint, true);
}
}
}
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 cbd3842a02..5e36dd0f78 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
@@ -4,7 +4,6 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.graphics.RectF;
-import android.location.Location;
import android.os.Bundle;
import android.support.annotation.FloatRange;
import android.support.annotation.IntRange;
@@ -16,7 +15,6 @@ import android.text.TextUtils;
import android.view.View;
import android.view.ViewGroup;
-import com.mapbox.android.core.location.LocationEngine;
import com.mapbox.android.gestures.AndroidGesturesManager;
import com.mapbox.android.gestures.MoveGestureDetector;
import com.mapbox.android.gestures.RotateGestureDetector;
@@ -39,13 +37,10 @@ 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.constants.MyBearingTracking;
-import com.mapbox.mapboxsdk.constants.MyLocationTracking;
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
-import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
-import com.mapbox.mapboxsdk.style.layers.Filter;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.light.Light;
import com.mapbox.mapboxsdk.style.sources.Source;
@@ -71,26 +66,21 @@ 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 CameraChangeDispatcher cameraChangeDispatcher;
private final OnGesturesManagerInteractionListener onGesturesManagerInteractionListener;
private MapboxMap.OnFpsChangedListener onFpsChangedListener;
- private PointF focalPoint;
- MapboxMap(NativeMapView map, Transform transform, UiSettings ui, TrackingSettings tracking,
- MyLocationViewSettings myLocationView, Projection projection, OnGesturesManagerInteractionListener listener,
- AnnotationManager annotations, CameraChangeDispatcher cameraChangeDispatcher) {
+ MapboxMap(NativeMapView map, Transform transform, UiSettings ui, Projection projection,
+ OnGesturesManagerInteractionListener listener, AnnotationManager annotations,
+ CameraChangeDispatcher cameraChangeDispatcher) {
this.nativeMapView = map;
this.uiSettings = ui;
- this.trackingSettings = tracking;
this.projection = projection;
- this.myLocationViewSettings = myLocationView;
this.annotationManager = annotations.bind(this);
this.transform = transform;
this.onGesturesManagerInteractionListener = listener;
@@ -100,8 +90,6 @@ public final class MapboxMap {
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());
@@ -115,8 +103,7 @@ public final class MapboxMap {
*/
void onStart() {
nativeMapView.update();
- trackingSettings.onStart();
- if (TextUtils.isEmpty(nativeMapView.getStyleUrl())) {
+ if (TextUtils.isEmpty(nativeMapView.getStyleUrl()) && TextUtils.isEmpty(nativeMapView.getStyleJson())) {
// if user hasn't loaded a Style yet
nativeMapView.setStyleUrl(Style.MAPBOX_STREETS);
}
@@ -126,7 +113,6 @@ public final class MapboxMap {
* Called when the hosting Activity/Fragment onStop() method is called.
*/
void onStop() {
- trackingSettings.onStop();
}
/**
@@ -138,9 +124,7 @@ public final class MapboxMap {
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);
- myLocationViewSettings.onSaveInstanceState(outState);
}
/**
@@ -151,9 +135,7 @@ public final class MapboxMap {
void onRestoreInstanceState(Bundle savedInstanceState) {
final CameraPosition cameraPosition = savedInstanceState.getParcelable(MapboxConstants.STATE_CAMERA_POSITION);
- myLocationViewSettings.onRestoreInstanceState(savedInstanceState);
uiSettings.onRestoreInstanceState(savedInstanceState);
- trackingSettings.onRestoreInstanceState(savedInstanceState);
if (cameraPosition != null) {
moveCamera(CameraUpdateFactory.newCameraPosition(
@@ -173,6 +155,7 @@ public final class MapboxMap {
* Called before the OnMapReadyCallback is invoked.
*/
void onPreMapReady() {
+ invalidateCameraPosition();
annotationManager.reloadMarkers();
annotationManager.adjustTopOffsetPixels(this);
}
@@ -192,7 +175,6 @@ public final class MapboxMap {
* Called when the region is changing or has changed.
*/
void onUpdateRegionChange() {
- trackingSettings.update();
annotationManager.update();
}
@@ -560,38 +542,6 @@ public final class MapboxMap {
}
//
- // TrackingSettings
- //
-
- /**
- * Gets the tracking interface settings for the map.
- *
- * @return the TrackingSettings asssociated with this map
- * @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
- */
- @Deprecated
- public TrackingSettings getTrackingSettings() {
- return trackingSettings;
- }
-
- //
- // MyLocationViewSettings
- //
-
- /**
- * Gets the settings of the user location for the map.
- *
- * @return the MyLocationViewSettings associated with this map
- * @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
- */
- @Deprecated
- public MyLocationViewSettings getMyLocationViewSettings() {
- return myLocationViewSettings;
- }
-
- //
// Projection
//
@@ -606,7 +556,7 @@ public final class MapboxMap {
}
//
- //
+ // Light
//
/**
@@ -624,47 +574,6 @@ public final class MapboxMap {
//
/**
- * 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
- */
- public void setLatLng(@NonNull LatLng latLng) {
- nativeMapView.setLatLng(latLng);
- }
-
- /**
- * Moves the camera viewpoint to a particular zoom level.
- *
- * @param zoom Zoom level to change to
- */
- public void setZoom(@FloatRange(from = MapboxConstants.MINIMUM_ZOOM, to = MapboxConstants.MAXIMUM_ZOOM) double zoom) {
- if (focalPoint == null) {
- focalPoint = new PointF(nativeMapView.getWidth() / 2, nativeMapView.getHeight() / 2);
- }
- nativeMapView.setZoom(zoom, focalPoint, 0);
- }
-
- /**
- * Moves the camera viewpoint angle to a particular angle in degrees.
- *
- * @param tilt Tilt angle to change to
- */
- public void setTilt(@FloatRange(from = MapboxConstants.MINIMUM_TILT, to = MapboxConstants.MAXIMUM_TILT) double tilt) {
- nativeMapView.setPitch(tilt, 0);
- }
-
- /**
- * Moves the camera viewpoint direction to a particular angle in degrees.
- *
- * @param bearing Direction angle to change to
- */
- public void setBearing(@FloatRange(from = MapboxConstants.MINIMUM_DIRECTION, to = MapboxConstants.MAXIMUM_DIRECTION)
- double bearing) {
- nativeMapView.setBearing(bearing);
- }
-
- /**
* Cancels ongoing animations.
* <p>
* This invokes the {@link CancelableCallback} for ongoing camera updates.
@@ -791,11 +700,6 @@ public final class MapboxMap {
* 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. You can change this behaviour by calling
- * {@link com.mapbox.mapboxsdk.maps.TrackingSettings#setDismissLocationTrackingOnGesture(boolean)} with false before
- * invoking this method and calling it with true in the {@link CancelableCallback#onFinish()}.
- * </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
@@ -817,11 +721,6 @@ public final class MapboxMap {
* 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. You can change this behaviour by calling
- * {@link com.mapbox.mapboxsdk.maps.TrackingSettings#setDismissLocationTrackingOnGesture(boolean)} with false before
- * invoking this method and calling it with true in the {@link CancelableCallback#onFinish()}.
- * </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
@@ -917,7 +816,7 @@ public final class MapboxMap {
/**
* Invalidates the current camera position by reconstructing it from mbgl
*/
- void invalidateCameraPosition() {
+ private void invalidateCameraPosition() {
CameraPosition cameraPosition = transform.invalidateCameraPosition();
if (cameraPosition != null) {
transform.updateCameraPosition(cameraPosition);
@@ -1652,19 +1551,8 @@ public final class MapboxMap {
* @return the camera position that fits the bounds and padding
*/
public CameraPosition getCameraForLatLngBounds(@Nullable LatLngBounds latLngBounds, int[] padding) {
- // calculate and set additional bounds padding
- int[] mapPadding = getPadding();
- for (int i = 0; i < padding.length; i++) {
- padding[i] = mapPadding[i] + padding[i];
- }
- projection.setContentPadding(padding, myLocationViewSettings.getPadding());
-
// get padded camera position from LatLngBounds
- CameraPosition cameraPosition = nativeMapView.getCameraForLatLngBounds(latLngBounds);
-
- // reset map padding
- setPadding(mapPadding);
- return cameraPosition;
+ return nativeMapView.getCameraForLatLngBounds(latLngBounds, padding);
}
/**
@@ -1676,19 +1564,8 @@ public final class MapboxMap {
* @return the camera position that fits the bounds and padding
*/
public CameraPosition getCameraForGeometry(Geometry geometry, double bearing, int[] padding) {
- // calculate and set additional bounds padding
- int[] mapPadding = getPadding();
- for (int i = 0; i < padding.length; i++) {
- padding[i] = mapPadding[i] + padding[i];
- }
- projection.setContentPadding(padding, myLocationViewSettings.getPadding());
-
- // get padded camera position from LatLngBounds
- CameraPosition cameraPosition = nativeMapView.getCameraForGeometry(geometry, bearing);
-
- // reset map padding
- setPadding(mapPadding);
- return cameraPosition;
+ // get padded camera position from Geometry
+ return nativeMapView.getCameraForGeometry(geometry, bearing, padding);
}
//
@@ -1697,13 +1574,13 @@ public final class MapboxMap {
/**
* <p>
- * Sets the distance from the edges of the map view’s frame to the edges of the map
- * view’s logical viewport.
+ * Sets the distance from the edges of the map view&#x27;s frame to the edges of the map
+ * view&#x27s 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
+ * properties such as &#x27;centerCoordinate&#x27; assume a viewport that matches the map
+ * view&#x27;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>
@@ -1718,7 +1595,7 @@ public final class MapboxMap {
}
private void setPadding(int[] padding) {
- projection.setContentPadding(padding, myLocationViewSettings.getPadding());
+ projection.setContentPadding(padding);
uiSettings.invalidate();
}
@@ -1763,7 +1640,7 @@ public final class MapboxMap {
*
* @param listener the listener to notify
*/
- public void addOnCameraIdleListener(@Nullable OnCameraIdleListener listener) {
+ public void addOnCameraIdleListener(@NonNull OnCameraIdleListener listener) {
cameraChangeDispatcher.addOnCameraIdleListener(listener);
}
@@ -1772,7 +1649,7 @@ public final class MapboxMap {
*
* @param listener the listener to remove
*/
- public void removeOnCameraIdleListener(@Nullable OnCameraIdleListener listener) {
+ public void removeOnCameraIdleListener(@NonNull OnCameraIdleListener listener) {
cameraChangeDispatcher.removeOnCameraIdleListener(listener);
}
@@ -1793,7 +1670,7 @@ public final class MapboxMap {
*
* @param listener the listener to notify
*/
- public void addOnCameraMoveCancelListener(@Nullable OnCameraMoveCanceledListener listener) {
+ public void addOnCameraMoveCancelListener(@NonNull OnCameraMoveCanceledListener listener) {
cameraChangeDispatcher.addOnCameraMoveCancelListener(listener);
}
@@ -1802,7 +1679,7 @@ public final class MapboxMap {
*
* @param listener the listener to remove
*/
- public void removeOnCameraMoveCancelListener(@Nullable OnCameraMoveCanceledListener listener) {
+ public void removeOnCameraMoveCancelListener(@NonNull OnCameraMoveCanceledListener listener) {
cameraChangeDispatcher.removeOnCameraMoveCancelListener(listener);
}
@@ -1823,7 +1700,7 @@ public final class MapboxMap {
*
* @param listener the listener to notify
*/
- public void addOnCameraMoveStartedListener(@Nullable OnCameraMoveStartedListener listener) {
+ public void addOnCameraMoveStartedListener(@NonNull OnCameraMoveStartedListener listener) {
cameraChangeDispatcher.addOnCameraMoveStartedListener(listener);
}
@@ -1832,7 +1709,7 @@ public final class MapboxMap {
*
* @param listener the listener to remove
*/
- public void removeOnCameraMoveStartedListener(@Nullable OnCameraMoveStartedListener listener) {
+ public void removeOnCameraMoveStartedListener(@NonNull OnCameraMoveStartedListener listener) {
cameraChangeDispatcher.removeOnCameraMoveStartedListener(listener);
}
@@ -1853,7 +1730,7 @@ public final class MapboxMap {
*
* @param listener the listener to notify
*/
- public void addOnCameraMoveListener(@Nullable OnCameraMoveListener listener) {
+ public void addOnCameraMoveListener(@NonNull OnCameraMoveListener listener) {
cameraChangeDispatcher.addOnCameraMoveListener(listener);
}
@@ -1862,7 +1739,7 @@ public final class MapboxMap {
*
* @param listener the listener to remove
*/
- public void removeOnCameraMoveListener(@Nullable OnCameraMoveListener listener) {
+ public void removeOnCameraMoveListener(@NonNull OnCameraMoveListener listener) {
cameraChangeDispatcher.removeOnCameraMoveListener(listener);
}
@@ -1898,9 +1775,8 @@ public final class MapboxMap {
* Adds 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.
*/
- public void addOnScrollListener(@Nullable OnScrollListener listener) {
+ public void addOnScrollListener(@NonNull OnScrollListener listener) {
onGesturesManagerInteractionListener.onAddScrollListener(listener);
}
@@ -1908,9 +1784,8 @@ public final class MapboxMap {
* Removes 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.
*/
- public void removeOnScrollListener(@Nullable OnScrollListener listener) {
+ public void removeOnScrollListener(@NonNull OnScrollListener listener) {
onGesturesManagerInteractionListener.onRemoveScrollListener(listener);
}
@@ -1930,9 +1805,8 @@ public final class MapboxMap {
* Adds 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.
*/
- public void addOnFlingListener(@Nullable OnFlingListener listener) {
+ public void addOnFlingListener(@NonNull OnFlingListener listener) {
onGesturesManagerInteractionListener.onAddFlingListener(listener);
}
@@ -1940,9 +1814,8 @@ public final class MapboxMap {
* Removes 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.
*/
- public void removeOnFlingListener(@Nullable OnFlingListener listener) {
+ public void removeOnFlingListener(@NonNull OnFlingListener listener) {
onGesturesManagerInteractionListener.onRemoveFlingListener(listener);
}
@@ -1951,7 +1824,7 @@ public final class MapboxMap {
*
* @param listener The callback that's invoked when the map is moved.
*/
- public void addOnMoveListener(OnMoveListener listener) {
+ public void addOnMoveListener(@NonNull OnMoveListener listener) {
onGesturesManagerInteractionListener.onAddMoveListener(listener);
}
@@ -1960,7 +1833,7 @@ public final class MapboxMap {
*
* @param listener The callback that's invoked when the map is moved.
*/
- public void removeOnMoveListener(OnMoveListener listener) {
+ public void removeOnMoveListener(@NonNull OnMoveListener listener) {
onGesturesManagerInteractionListener.onRemoveMoveListener(listener);
}
@@ -1969,7 +1842,7 @@ public final class MapboxMap {
*
* @param listener The callback that's invoked when the map is rotated.
*/
- public void addOnRotateListener(OnRotateListener listener) {
+ public void addOnRotateListener(@NonNull OnRotateListener listener) {
onGesturesManagerInteractionListener.onAddRotateListener(listener);
}
@@ -1978,7 +1851,7 @@ public final class MapboxMap {
*
* @param listener The callback that's invoked when the map is rotated.
*/
- public void removeOnRotateListener(OnRotateListener listener) {
+ public void removeOnRotateListener(@NonNull OnRotateListener listener) {
onGesturesManagerInteractionListener.onRemoveRotateListener(listener);
}
@@ -1987,7 +1860,7 @@ public final class MapboxMap {
*
* @param listener The callback that's invoked when the map is scaled.
*/
- public void addOnScaleListener(OnScaleListener listener) {
+ public void addOnScaleListener(@NonNull OnScaleListener listener) {
onGesturesManagerInteractionListener.onAddScaleListener(listener);
}
@@ -1996,7 +1869,7 @@ public final class MapboxMap {
*
* @param listener The callback that's invoked when the map is scaled.
*/
- public void removeOnScaleListener(OnScaleListener listener) {
+ public void removeOnScaleListener(@NonNull OnScaleListener listener) {
onGesturesManagerInteractionListener.onRemoveScaleListener(listener);
}
@@ -2005,7 +1878,7 @@ public final class MapboxMap {
*
* @param listener The callback that's invoked when the map is tilted.
*/
- public void addOnShoveListener(OnShoveListener listener) {
+ public void addOnShoveListener(@NonNull OnShoveListener listener) {
onGesturesManagerInteractionListener.onAddShoveListener(listener);
}
@@ -2014,22 +1887,30 @@ public final class MapboxMap {
*
* @param listener The callback that's invoked when the map is tilted.
*/
- public void removeOnShoveListener(OnShoveListener listener) {
+ public void removeOnShoveListener(@NonNull OnShoveListener listener) {
onGesturesManagerInteractionListener.onRemoveShoveListener(listener);
}
/**
- * Sets a custom {@link AndroidGesturesManager} to handle {@link android.view.MotionEvent}s registered by the map.
+ * Sets a custom {@link AndroidGesturesManager} to handle {@link android.view.MotionEvent}s
+ * registered by the {@link MapView}.
*
- * @param androidGesturesManager Gestures manager that interprets gestures based on the motion events.
+ * @param androidGesturesManager Gestures manager that interprets gestures based on the motion events.
+ * @param attachDefaultListeners If true, pre-defined listeners will be attach
+ * to change map based on {@link AndroidGesturesManager} callbacks.
+ * @param setDefaultMutuallyExclusives If true, pre-defined mutually exclusive gesture sets
+ * will be added to the passed gestures manager.
* @see <a href="https://github.com/mapbox/mapbox-gestures-android">mapbox-gestures-android library</a>
*/
- public void setGesturesManager(AndroidGesturesManager androidGesturesManager) {
- onGesturesManagerInteractionListener.setGesturesManager(androidGesturesManager);
+ public void setGesturesManager(AndroidGesturesManager androidGesturesManager, boolean attachDefaultListeners,
+ boolean setDefaultMutuallyExclusives) {
+ onGesturesManagerInteractionListener.setGesturesManager(
+ androidGesturesManager, attachDefaultListeners, setDefaultMutuallyExclusives);
}
/**
- * Get current {@link AndroidGesturesManager} that handles {@link android.view.MotionEvent}s registered by the map.
+ * Get current {@link AndroidGesturesManager} that handles {@link android.view.MotionEvent}s
+ * registered by the {@link MapView}
*
* @return Current gestures manager.
*/
@@ -2038,6 +1919,13 @@ public final class MapboxMap {
}
/**
+ * Interrupts any ongoing gesture velocity animations.
+ */
+ public void cancelAllVelocityAnimations() {
+ onGesturesManagerInteractionListener.cancelAllVelocityAnimations();
+ }
+
+ /**
* 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.
@@ -2053,9 +1941,8 @@ public final class MapboxMap {
* Adds 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.
*/
- public void addOnMapClickListener(@Nullable OnMapClickListener listener) {
+ public void addOnMapClickListener(@NonNull OnMapClickListener listener) {
onGesturesManagerInteractionListener.onAddMapClickListener(listener);
}
@@ -2063,9 +1950,8 @@ public final class MapboxMap {
* Removes 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.
*/
- public void removeOnMapClickListener(@Nullable OnMapClickListener listener) {
+ public void removeOnMapClickListener(@NonNull OnMapClickListener listener) {
onGesturesManagerInteractionListener.onRemoveMapClickListener(listener);
}
@@ -2085,9 +1971,8 @@ public final class MapboxMap {
* Adds 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.
*/
- public void addOnMapLongClickListener(@Nullable OnMapLongClickListener listener) {
+ public void addOnMapLongClickListener(@NonNull OnMapLongClickListener listener) {
onGesturesManagerInteractionListener.onAddMapLongClickListener(listener);
}
@@ -2095,9 +1980,8 @@ public final class MapboxMap {
* Removes 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.
*/
- public void removeOnMapLongClickListener(@Nullable OnMapLongClickListener listener) {
+ public void removeOnMapLongClickListener(@NonNull OnMapLongClickListener listener) {
onGesturesManagerInteractionListener.onRemoveMapLongClickListener(listener);
}
@@ -2159,107 +2043,6 @@ public final class MapboxMap {
}
//
- // User location
- //
-
- /**
- * Returns the status of the my-location layer.
- *
- * @return True if the my-location layer is enabled, false otherwise.
- * @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
- */
- @Deprecated
- 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.
- * @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
- */
- @Deprecated
- 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.
- * @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
- */
- @Nullable
- @Deprecated
- 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.
- * @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
- */
- @Deprecated
- public void setOnMyLocationChangeListener(@Nullable MapboxMap.OnMyLocationChangeListener
- listener) {
- trackingSettings.setOnMyLocationChangeListener(listener);
- }
-
- /**
- * Replaces the location source of the my-location layer.
- *
- * @param locationSource A {@link LocationEngine} location source to use in the my-location layer.
- * @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
- */
- @Deprecated
- public void setLocationSource(@Nullable LocationEngine locationSource) {
- trackingSettings.setLocationSource(locationSource);
- }
-
- /**
- * 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.
- * @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
- */
- @Deprecated
- 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.
- * @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugin-locationlayer instead.
- */
- @Deprecated
- public void setOnMyBearingTrackingModeChangeListener(@Nullable OnMyBearingTrackingModeChangeListener listener) {
- trackingSettings.setOnMyBearingTrackingModeChangeListener(listener);
- }
-
- //
// Invalidate
//
@@ -2289,13 +2072,13 @@ public final class MapboxMap {
* Queries the map for rendered features
*
* @param coordinates the point to query
- * @param filter filters the returned features
+ * @param filter filters the returned features with an expression
* @param layerIds optionally - only query these layers
* @return the list of feature
*/
@NonNull
public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates,
- @Nullable Filter.Statement filter,
+ @Nullable Expression filter,
@Nullable String... layerIds) {
return nativeMapView.queryRenderedFeatures(coordinates, layerIds, filter);
}
@@ -2317,26 +2100,17 @@ public final class MapboxMap {
* Queries the map for rendered features
*
* @param coordinates the box to query
- * @param filter filters the returned features
+ * @param filter filters the returned features with an expression
* @param layerIds optionally - only query these layers
* @return the list of feature
*/
@NonNull
public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates,
- @Nullable Filter.Statement filter,
+ @Nullable Expression filter,
@Nullable String... layerIds) {
return nativeMapView.queryRenderedFeatures(coordinates, layerIds, filter);
}
- FocalPointChangeListener createFocalPointChangeListener() {
- return new FocalPointChangeListener() {
- @Override
- public void onFocalPointChanged(PointF pointF) {
- focalPoint = pointF;
- }
- };
- }
-
//
// Interfaces
//
@@ -2564,7 +2338,10 @@ public final class MapboxMap {
AndroidGesturesManager getGesturesManager();
- void setGesturesManager(AndroidGesturesManager gesturesManager);
+ void setGesturesManager(AndroidGesturesManager gesturesManager, boolean attachDefaultListeners,
+ boolean setDefaultMutuallyExclusives);
+
+ void cancelAllVelocityAnimations();
}
/**
@@ -2837,51 +2614,6 @@ public final class MapboxMap {
}
/**
- * 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 TrackingSettings#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 TrackingSettings#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 {
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 46dba28b98..bb4e2f9212 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
@@ -8,10 +8,8 @@ import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.ColorInt;
-import android.support.annotation.IntRange;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-import android.support.v4.content.ContextCompat;
import android.support.v4.content.res.ResourcesCompat;
import android.util.AttributeSet;
import android.view.Gravity;
@@ -20,7 +18,6 @@ import com.mapbox.mapboxsdk.R;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.constants.MapboxConstants;
import com.mapbox.mapboxsdk.utils.BitmapUtils;
-import com.mapbox.mapboxsdk.utils.ColorUtils;
import java.util.Arrays;
@@ -68,18 +65,6 @@ public class MapboxMapOptions implements Parcelable {
private boolean zoomControlsEnabled = false;
private boolean doubleTapGesturesEnabled = true;
- private boolean myLocationEnabled;
- private Drawable myLocationForegroundDrawable;
- private Drawable myLocationForegroundBearingDrawable;
- private Drawable myLocationBackgroundDrawable;
- @ColorInt
- private int myLocationForegroundTintColor = UNDEFINED_COLOR;
- @ColorInt
- private int myLocationBackgroundTintColor = UNDEFINED_COLOR;
- private int[] myLocationBackgroundPadding;
- private int myLocationAccuracyTintColor;
- private int myLocationAccuracyAlpha;
- private float myLocationAccuracyThreshold;
private boolean prefetchesTiles = true;
private boolean zMediaOverlay = false;
private String localIdeographFontFamily;
@@ -87,6 +72,7 @@ public class MapboxMapOptions implements Parcelable {
private String apiBaseUrl;
private boolean textureMode;
+ private boolean translucentTextureSurface;
private String style;
@@ -129,33 +115,10 @@ public class MapboxMapOptions implements Parcelable {
zoomGesturesEnabled = in.readByte() != 0;
doubleTapGesturesEnabled = 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();
- myLocationAccuracyThreshold = in.readFloat();
-
style = in.readString();
apiBaseUrl = in.readString();
textureMode = in.readByte() != 0;
+ translucentTextureSurface = in.readByte() != 0;
prefetchesTiles = in.readByte() != 0;
zMediaOverlay = in.readByte() != 0;
localIdeographFontFamily = in.readString();
@@ -245,50 +208,10 @@ public class MapboxMapOptions implements Parcelable {
(int) (typedArray.getDimension(R.styleable.mapbox_MapView_mapbox_uiAttributionMarginBottom,
FOUR_DP * pxlRatio))});
- mapboxMapOptions.locationEnabled(typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_myLocation, false));
- mapboxMapOptions.myLocationForegroundTintColor(
- typedArray.getColor(R.styleable.mapbox_MapView_mapbox_myLocationTintColor, UNDEFINED_COLOR));
- mapboxMapOptions.myLocationBackgroundTintColor(
- typedArray.getColor(R.styleable.mapbox_MapView_mapbox_myLocationBackgroundTintColor, UNDEFINED_COLOR));
-
- 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.myLocationAccuracyThreshold(
- typedArray.getFloat(R.styleable.mapbox_MapView_mapbox_myLocationAccuracyThreshold, 0));
mapboxMapOptions.textureMode(
typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_renderTextureMode, false));
+ mapboxMapOptions.translucentTextureSurface(
+ typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_renderTextureTranslucentSurface, false));
mapboxMapOptions.setPrefetchesTiles(
typedArray.getBoolean(R.styleable.mapbox_MapView_mapbox_enableTilePrefetch, true));
mapboxMapOptions.renderSurfaceOnTop(
@@ -572,128 +495,6 @@ public class MapboxMapOptions implements Parcelable {
}
/**
- * 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 drawable
- * @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;
- }
-
- /**
- * Set accuracy circle threshold. Circle won't be displayed if accuracy is below set value.
- *
- * @param myLocationAccuracyThreshold Value of accuracy (in meters), below which circle won't be displayed
- * @return This
- */
- public MapboxMapOptions myLocationAccuracyThreshold(float myLocationAccuracyThreshold) {
- this.myLocationAccuracyThreshold = myLocationAccuracyThreshold;
- return this;
- }
-
- /**
* Enable {@link android.view.TextureView} as rendered surface.
* <p>
* Since the 5.2.0 release we replaced our TextureView with an {@link android.opengl.GLSurfaceView}
@@ -711,6 +512,11 @@ public class MapboxMapOptions implements Parcelable {
return this;
}
+ public MapboxMapOptions translucentTextureSurface(boolean translucentTextureSurface) {
+ this.translucentTextureSurface = translucentTextureSurface;
+ return this;
+ }
+
/**
* Enable tile pre-fetching. Loads tiles at a lower zoom-level to pre-render
* a low resolution preview while more detailed tiles are loaded.
@@ -725,11 +531,11 @@ public class MapboxMapOptions implements Parcelable {
}
/**
- * Set the font family for generating glyphs locally for ideographs in the ‘CJK Unified Ideographs’
- * and ‘Hangul Syllables’ ranges.
- *
+ * Set the font family for generating glyphs locally for ideographs in the &#x27;CJK Unified Ideographs&#x27;
+ * and &#x27;Hangul Syllables&#x27; ranges.
+ * <p>
* The font family argument is passed to {@link android.graphics.Typeface#create(String, int)}.
- * Default system fonts are defined in '/system/etc/fonts.xml'
+ * Default system fonts are defined in &#x27;/system/etc/fonts.xml&#x27;
*
* @param fontFamily font family for local ideograph generation.
* @return This
@@ -976,98 +782,6 @@ public class MapboxMapOptions implements Parcelable {
}
/**
- * 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
- */
- @ColorInt
- public int getMyLocationForegroundTintColor() {
- return myLocationForegroundTintColor;
- }
-
- /**
- * Get the current configured MyLocationView background tint color.
- *
- * @return the tint color
- */
- @ColorInt
- 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;
- }
-
- /**
- * Returns current accuracy threshold value (in meters).
- *
- * @return Value of accuracy threshold (in meters), below which circle won't be displayed
- */
- public float getMyLocationAccuracyThreshold() {
- return myLocationAccuracyThreshold;
- }
-
- /**
* Get the current configured debug state for a map view.
*
* @return True indicates debug is enabled.
@@ -1085,9 +799,13 @@ public class MapboxMapOptions implements Parcelable {
return textureMode;
}
+ public boolean getTranslucentTextureSurface() {
+ return translucentTextureSurface;
+ }
+
/**
* Returns the font-family for locally overriding generation of glyphs in the
- * ‘CJK Unified Ideographs’ and ‘Hangul Syllables’ ranges.
+ * &#x27;CJK Unified Ideographs&#x27; and &#x27;Hangul Syllables&#x27; ranges.
*
* @return Local ideograph font family name.
*/
@@ -1141,24 +859,10 @@ public class MapboxMapOptions implements Parcelable {
dest.writeByte((byte) (zoomGesturesEnabled ? 1 : 0));
dest.writeByte((byte) (doubleTapGesturesEnabled ? 1 : 0));
- dest.writeByte((byte) (myLocationEnabled ? 1 : 0));
-
- dest.writeParcelable(myLocationForegroundDrawable != null
- ? BitmapUtils.getBitmapFromDrawable(myLocationForegroundDrawable) : null, flags);
- dest.writeParcelable(myLocationForegroundBearingDrawable != null
- ? BitmapUtils.getBitmapFromDrawable(myLocationForegroundBearingDrawable) : null, flags);
- dest.writeParcelable(myLocationBackgroundDrawable != null
- ? BitmapUtils.getBitmapFromDrawable(myLocationBackgroundDrawable) : null, flags);
- dest.writeInt(myLocationForegroundTintColor);
- dest.writeInt(myLocationBackgroundTintColor);
- dest.writeIntArray(myLocationBackgroundPadding);
- dest.writeInt(myLocationAccuracyAlpha);
- dest.writeInt(myLocationAccuracyTintColor);
- dest.writeFloat(myLocationAccuracyThreshold);
-
dest.writeString(style);
dest.writeString(apiBaseUrl);
dest.writeByte((byte) (textureMode ? 1 : 0));
+ dest.writeByte((byte) (translucentTextureSurface ? 1 : 0));
dest.writeByte((byte) (prefetchesTiles ? 1 : 0));
dest.writeByte((byte) (zMediaOverlay ? 1 : 0));
dest.writeString(localIdeographFontFamily);
@@ -1231,24 +935,6 @@ public class MapboxMapOptions implements Parcelable {
if (doubleTapGesturesEnabled != options.doubleTapGesturesEnabled) {
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 (myLocationAccuracyThreshold != options.myLocationAccuracyThreshold) {
- return false;
- }
if (cameraPosition != null ? !cameraPosition.equals(options.cameraPosition) : options.cameraPosition != null) {
return false;
}
@@ -1261,24 +947,6 @@ public class MapboxMapOptions implements Parcelable {
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;
}
@@ -1326,20 +994,9 @@ public class MapboxMapOptions implements Parcelable {
result = 31 * result + (zoomGesturesEnabled ? 1 : 0);
result = 31 * result + (zoomControlsEnabled ? 1 : 0);
result = 31 * result + (doubleTapGesturesEnabled ? 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 + (myLocationAccuracyThreshold != +0.0f
- ? Float.floatToIntBits(myLocationAccuracyThreshold) : 0);
result = 31 * result + (apiBaseUrl != null ? apiBaseUrl.hashCode() : 0);
result = 31 * result + (textureMode ? 1 : 0);
+ result = 31 * result + (translucentTextureSurface ? 1 : 0);
result = 31 * result + (style != null ? style.hashCode() : 0);
result = 31 * result + (prefetchesTiles ? 1 : 0);
result = 31 * result + (zMediaOverlay ? 1 : 0);
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 785b045779..976277dcac 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
@@ -24,8 +24,8 @@ import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.geometry.ProjectedMeters;
import com.mapbox.mapboxsdk.maps.renderer.MapRenderer;
import com.mapbox.mapboxsdk.storage.FileSource;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.CannotAddLayerException;
-import com.mapbox.mapboxsdk.style.layers.Filter;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.light.Light;
import com.mapbox.mapboxsdk.style.sources.CannotAddSourceException;
@@ -229,18 +229,28 @@ final class NativeMapView {
return nativeGetLatLng().wrap();
}
- public CameraPosition getCameraForLatLngBounds(LatLngBounds latLngBounds) {
+ public CameraPosition getCameraForLatLngBounds(LatLngBounds latLngBounds, int[] padding) {
if (isDestroyedOn("getCameraForLatLngBounds")) {
return null;
}
- return nativeGetCameraForLatLngBounds(latLngBounds);
+ return nativeGetCameraForLatLngBounds(
+ latLngBounds,
+ padding[1] / pixelRatio,
+ padding[0] / pixelRatio,
+ padding[3] / pixelRatio,
+ padding[2] / pixelRatio);
}
- public CameraPosition getCameraForGeometry(Geometry geometry, double bearing) {
+ public CameraPosition getCameraForGeometry(Geometry geometry, double bearing, int[] padding) {
if (isDestroyedOn("getCameraForGeometry")) {
return null;
}
- return nativeGetCameraForGeometry(geometry, bearing);
+ return nativeGetCameraForGeometry(
+ geometry, bearing,
+ padding[1] / pixelRatio,
+ padding[0] / pixelRatio,
+ padding[3] / pixelRatio,
+ padding[2] / pixelRatio);
}
public void resetPosition() {
@@ -758,20 +768,8 @@ final class NativeMapView {
return;
}
- // 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);
-
// Determine pixel ratio
- float density = image.getDensity() == Bitmap.DENSITY_NONE ? Bitmap.DENSITY_NONE : image.getDensity();
- float pixelRatio = density / DisplayMetrics.DENSITY_DEFAULT;
-
- nativeAddImage(name, image.getWidth(), image.getHeight(), pixelRatio, buffer.array());
+ nativeAddImage(name, image, image.getDensity() / DisplayMetrics.DENSITY_DEFAULT);
}
public void addImages(@NonNull HashMap<String, Bitmap> bitmapHashMap) {
@@ -801,7 +799,7 @@ final class NativeMapView {
@NonNull
public List<Feature> queryRenderedFeatures(@NonNull PointF coordinates,
@Nullable String[] layerIds,
- @Nullable Filter.Statement filter) {
+ @Nullable Expression filter) {
if (isDestroyedOn("queryRenderedFeatures")) {
return new ArrayList<>();
}
@@ -813,7 +811,7 @@ final class NativeMapView {
@NonNull
public List<Feature> queryRenderedFeatures(@NonNull RectF coordinates,
@Nullable String[] layerIds,
- @Nullable Filter.Statement filter) {
+ @Nullable Expression filter) {
if (isDestroyedOn("queryRenderedFeatures")) {
return new ArrayList<>();
}
@@ -908,9 +906,11 @@ final class NativeMapView {
private native LatLng nativeGetLatLng();
- private native CameraPosition nativeGetCameraForLatLngBounds(LatLngBounds latLngBounds);
+ private native CameraPosition nativeGetCameraForLatLngBounds(
+ LatLngBounds latLngBounds, double top, double left, double bottom, double right);
- private native CameraPosition nativeGetCameraForGeometry(Geometry geometry, double bearing);
+ private native CameraPosition nativeGetCameraForGeometry(
+ Geometry geometry, double bearing, double top, double left, double bottom, double right);
private native void nativeResetPosition();
@@ -1032,8 +1032,7 @@ final class NativeMapView {
private native void nativeRemoveSource(Source source, long sourcePtr);
- private native void nativeAddImage(String name, int width, int height, float pixelRatio,
- byte[] array);
+ private native void nativeAddImage(String name, Bitmap bitmap, float pixelRatio);
private native void nativeAddImages(Image[] images);
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 ae559189ad..f35355533d 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
@@ -9,6 +9,9 @@ import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.geometry.ProjectedMeters;
import com.mapbox.mapboxsdk.geometry.VisibleRegion;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* A projection is used to translate between on screen location and geographic coordinates on
* the surface of the Earth. Screen location is in screen pixels (not display pixels)
@@ -24,25 +27,17 @@ public class Projection {
this.contentPadding = new int[] {0, 0, 0, 0};
}
- void setContentPadding(int[] contentPadding, int[] userLocationViewPadding) {
+ void setContentPadding(int[] contentPadding) {
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);
+ nativeMapView.setContentPadding(contentPadding);
}
int[] getContentPadding() {
return contentPadding;
}
- public void invalidateContentPadding(int[] userLocationViewPadding) {
- setContentPadding(contentPadding, userLocationViewPadding);
+ public void invalidateContentPadding() {
+ setContentPadding(contentPadding);
}
/**
@@ -103,14 +98,49 @@ public class Projection {
LatLng bottomRight = fromScreenLocation(new PointF(right, bottom));
LatLng bottomLeft = fromScreenLocation(new PointF(left, bottom));
- return new VisibleRegion(topLeft, topRight, bottomLeft, bottomRight,
- new LatLngBounds.Builder()
- .include(topRight)
- .include(bottomLeft)
- .include(bottomRight)
- .include(topLeft)
- .build()
- );
+ // Map can be rotated, find correct LatLngBounds that encompasses the visible region (that might be rotated)
+ List<LatLng> boundsPoints = new ArrayList<>();
+ boundsPoints.add(topLeft);
+ boundsPoints.add(topRight);
+ boundsPoints.add(bottomRight);
+ boundsPoints.add(bottomLeft);
+
+ // order so that two most northern point are put first
+ while ((boundsPoints.get(0).getLatitude() < boundsPoints.get(3).getLatitude())
+ || (boundsPoints.get(1).getLatitude() < boundsPoints.get(2).getLatitude())) {
+ LatLng first = boundsPoints.remove(0);
+ boundsPoints.add(first);
+ }
+
+ double north = boundsPoints.get(0).getLatitude();
+ if (north < boundsPoints.get(1).getLatitude()) {
+ north = boundsPoints.get(1).getLatitude();
+ }
+
+ double south = boundsPoints.get(2).getLatitude();
+ if (south > boundsPoints.get(3).getLatitude()) {
+ south = boundsPoints.get(3).getLatitude();
+ }
+
+ double firstLon = boundsPoints.get(0).getLongitude();
+ double secondLon = boundsPoints.get(1).getLongitude();
+ double thridLon = boundsPoints.get(2).getLongitude();
+ double fourthLon = boundsPoints.get(3).getLongitude();
+
+ // if it does not go over the date line
+ if (secondLon > fourthLon && firstLon < thridLon) {
+ return new VisibleRegion(topLeft, topRight, bottomLeft, bottomRight,
+ LatLngBounds.from(north,
+ secondLon > thridLon ? secondLon : thridLon,
+ south,
+ firstLon < fourthLon ? firstLon : fourthLon));
+ } else {
+ return new VisibleRegion(topLeft, topRight, bottomLeft, bottomRight,
+ LatLngBounds.from(north,
+ secondLon < thridLon ? secondLon : thridLon,
+ south,
+ firstLon > fourthLon ? firstLon : fourthLon));
+ }
}
/**
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Events.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Telemetry.java
index a68d4763ac..e6b93e4b91 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Events.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/Telemetry.java
@@ -2,11 +2,12 @@ package com.mapbox.mapboxsdk.maps;
import com.mapbox.android.telemetry.MapboxTelemetry;
+import com.mapbox.android.telemetry.SessionInterval;
import com.mapbox.android.telemetry.TelemetryEnabler;
import com.mapbox.mapboxsdk.BuildConfig;
import com.mapbox.mapboxsdk.Mapbox;
-class Events {
+public class Telemetry {
static final String TWO_FINGER_TAP = "TwoFingerTap";
static final String DOUBLE_TAP = "DoubleTap";
static final String SINGLE_TAP = "SingleTap";
@@ -16,21 +17,32 @@ class Events {
static final String PITCH = "Pitch";
private MapboxTelemetry telemetry;
- private Events() {
+ private Telemetry() {
telemetry = new MapboxTelemetry(Mapbox.getApplicationContext(), Mapbox.getAccessToken(),
BuildConfig.MAPBOX_EVENTS_USER_AGENT);
TelemetryEnabler.State telemetryState = TelemetryEnabler.retrieveTelemetryStateFromPreferences();
- if (TelemetryEnabler.State.NOT_INITIALIZED.equals(telemetryState)
- || TelemetryEnabler.State.ENABLED.equals(telemetryState)) {
+ if (TelemetryEnabler.State.ENABLED.equals(telemetryState)) {
telemetry.enable();
}
}
- private static class EventsHolder {
- private static final Events INSTANCE = new Events();
+ public static void initialize() {
+ obtainTelemetry();
+ }
+
+ public static void updateDebugLoggingEnabled(boolean debugLoggingEnabled) {
+ TelemetryHolder.INSTANCE.telemetry.updateDebugLoggingEnabled(debugLoggingEnabled);
+ }
+
+ public static boolean updateSessionIdRotationInterval(SessionInterval interval) {
+ return TelemetryHolder.INSTANCE.telemetry.updateSessionIdRotationInterval(interval);
+ }
+
+ private static class TelemetryHolder {
+ private static final Telemetry INSTANCE = new Telemetry();
}
static MapboxTelemetry obtainTelemetry() {
- return EventsHolder.INSTANCE.telemetry;
+ return TelemetryHolder.INSTANCE.telemetry;
}
}
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
deleted file mode 100644
index 3743096824..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/TrackingSettings.java
+++ /dev/null
@@ -1,419 +0,0 @@
-package com.mapbox.mapboxsdk.maps;
-
-import android.location.Location;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.annotation.UiThread;
-
-import com.mapbox.mapboxsdk.Mapbox;
-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.maps.widgets.MyLocationView;
-import com.mapbox.android.core.location.LocationEngine;
-import com.mapbox.android.core.location.LocationEngineListener;
-import com.mapbox.android.core.permissions.PermissionsManager;
-
-import timber.log.Timber;
-
-/**
- * Settings for the user location and bearing tracking of a MapboxMap.
- *
- * @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugins/locationlayer instead.
- */
-@Deprecated
-public final class TrackingSettings {
-
- private final MyLocationView myLocationView;
- private final UiSettings uiSettings;
- private final FocalPointChangeListener focalPointChangedListener;
- private final CameraZoomInvalidator zoomInvalidator;
- private LocationEngine locationSource;
- private LocationEngineListener myLocationListener;
- private boolean locationChangeAnimationEnabled = true;
- private boolean isCustomLocationSource;
-
- private boolean myLocationEnabled;
- private boolean dismissLocationTrackingOnGesture = true;
- private boolean dismissBearingTrackingOnGesture = true;
-
- private MapboxMap.OnMyLocationTrackingModeChangeListener onMyLocationTrackingModeChangeListener;
- private MapboxMap.OnMyBearingTrackingModeChangeListener onMyBearingTrackingModeChangeListener;
-
- TrackingSettings(@NonNull MyLocationView myLocationView, UiSettings uiSettings,
- FocalPointChangeListener focalPointChangedListener, CameraZoomInvalidator zoomInvalidator) {
- this.myLocationView = myLocationView;
- this.focalPointChangedListener = focalPointChangedListener;
- this.uiSettings = uiSettings;
- this.zoomInvalidator = zoomInvalidator;
- }
-
- void initialise(MapboxMapOptions options) {
- locationSource = Mapbox.getLocationEngine();
- setMyLocationEnabled(options.getLocationEnabled());
- }
-
- 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());
- outState.putBoolean(MapboxConstants.STATE_LOCATION_CHANGE_ANIMATION_ENABLED, isLocationChangeAnimationEnabled());
- outState.putBoolean(MapboxConstants.STATE_USING_CUSTOM_LOCATION_SOURCE, isCustomLocationSource());
- }
-
- void onRestoreInstanceState(Bundle savedInstanceState) {
- try {
- setMyLocationEnabled(
- savedInstanceState.getBoolean(MapboxConstants.STATE_MY_LOCATION_ENABLED),
- savedInstanceState.getBoolean(MapboxConstants.STATE_USING_CUSTOM_LOCATION_SOURCE)
- );
- } 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));
- setLocationChangeAnimationEnabled(savedInstanceState.getBoolean(
- MapboxConstants.STATE_LOCATION_CHANGE_ANIMATION_ENABLED, true));
- }
-
- /**
- * <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.setLocationChangeAnimationEnabled(isLocationChangeAnimationEnabled());
- myLocationView.setMyLocationTrackingMode(myLocationTrackingMode);
-
- if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW) {
- zoomInvalidator.zoomTo(2.0);
- focalPointChangedListener.onFocalPointChanged(myLocationView.getCenter());
- } else {
- focalPointChangedListener.onFocalPointChanged(null);
- }
-
- if (onMyLocationTrackingModeChangeListener != null) {
- onMyLocationTrackingModeChangeListener.onMyLocationTrackingModeChange(myLocationTrackingMode);
- }
- }
-
- /**
- * 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();
- }
-
- /**
- * <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);
- }
- }
-
- /**
- * 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 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 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 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);
- }
-
- /**
- * Returns whether location change animation is applied for {@link MyLocationTracking#TRACKING_FOLLOW}.
- *
- * @return True if animation is applied, false otherwise.
- */
- public boolean isLocationChangeAnimationEnabled() {
- return locationChangeAnimationEnabled;
- }
-
- /**
- * Set whether location change animation should be applied for {@link MyLocationTracking#TRACKING_FOLLOW}.
- *
- * @param locationChangeAnimationEnabled True if animation should be applied, false otherwise.
- */
- public void setLocationChangeAnimationEnabled(boolean locationChangeAnimationEnabled) {
- this.locationChangeAnimationEnabled = locationChangeAnimationEnabled;
-
- myLocationView.setLocationChangeAnimationEnabled(locationChangeAnimationEnabled);
- }
-
- /**
- * Reset the tracking modes as necessary. Location tracking is reset if the map center is changed and not from
- * location, bearing tracking if there is a rotation.
- *
- * @param translate true if translation
- * @param rotate true if rotation
- * @param isFromLocation true if from location
- */
- void resetTrackingModesIfRequired(boolean translate, boolean rotate, boolean isFromLocation) {
- // if tracking is on, and we should dismiss tracking with gestures, and this is a scroll action, turn tracking off
- if (translate && !isLocationTrackingDisabled() && isDismissLocationTrackingOnGesture() && !isFromLocation) {
- setMyLocationTrackingMode(MyLocationTracking.TRACKING_NONE);
- }
-
- // reset bearing tracking only on rotate
- if (rotate && !isBearingTrackingDisabled() && isDismissBearingTrackingOnGesture()) {
- setMyBearingTrackingMode(MyBearingTracking.NONE);
- }
- }
-
- /**
- * Reset the tracking modes as necessary. Animated camera position changes can reset the underlying tracking modes.
- *
- * @param currentCameraPosition the current camera position
- * @param targetCameraPosition the changed camera position
- * @param isFromLocation true if from location
- */
- void resetTrackingModesIfRequired(CameraPosition currentCameraPosition, CameraPosition targetCameraPosition,
- boolean isFromLocation) {
- if (currentCameraPosition.target != null) {
- resetTrackingModesIfRequired(!currentCameraPosition.target.equals(targetCameraPosition.target), false,
- isFromLocation);
- }
- }
-
- Location getMyLocation() {
- return myLocationView.getLocation();
- }
-
- void setOnMyLocationChangeListener(@Nullable final MapboxMap.OnMyLocationChangeListener listener) {
- if (listener != null) {
- myLocationListener = new LocationEngineListener() {
- @Override
- public void onConnected() {
- // Nothing
- }
-
- @Override
- public void onLocationChanged(Location location) {
- if (listener != null) {
- listener.onMyLocationChange(location);
- }
- }
- };
- locationSource.addLocationEngineListener(myLocationListener);
- } else {
- locationSource.removeLocationEngineListener(myLocationListener);
- myLocationListener = null;
- }
- }
-
- public boolean isCustomLocationSource() {
- return isCustomLocationSource;
- }
-
- 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) {
- setMyLocationEnabled(locationEnabled, isCustomLocationSource());
- }
-
- private void setMyLocationEnabled(boolean locationEnabled, boolean isCustomLocationSource) {
- if (locationEnabled && !PermissionsManager.areLocationPermissionsGranted(myLocationView.getContext())) {
- Timber.e("Could not activate user location tracking: "
- + "user did not accept the permission or permissions were not requested.");
- return;
- }
- myLocationEnabled = locationEnabled;
- this.isCustomLocationSource = isCustomLocationSource;
- myLocationView.setEnabled(locationEnabled, isCustomLocationSource);
- }
-
- void setLocationSource(LocationEngine locationSource) {
- if (this.locationSource != null && this.locationSource.equals(locationSource)) {
- // this source is already active
- return;
- }
-
- this.isCustomLocationSource = locationSource != null;
- if (locationSource == null) {
- locationSource = Mapbox.getLocationEngine();
- }
- this.locationSource = locationSource;
- myLocationView.setLocationSource(locationSource);
- }
-
- void update() {
- if (!myLocationView.isEnabled()) {
- return;
- }
- myLocationView.update();
- }
-
- void onStart() {
- myLocationView.onStart();
- }
-
- void onStop() {
- myLocationView.onStop();
- }
-
- interface CameraZoomInvalidator {
- void zoomTo(double zoomLevel);
- }
-}
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
index 43c943a16f..f76e54984b 100644
--- 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
@@ -12,7 +12,6 @@ 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 timber.log.Timber;
@@ -30,8 +29,6 @@ final class Transform implements MapView.OnMapChangedListener {
private final NativeMapView mapView;
private final MarkerViewManager markerViewManager;
- private final TrackingSettings trackingSettings;
- private final MyLocationView myLocationView;
private final Handler handler = new Handler();
private CameraPosition cameraPosition;
@@ -41,12 +38,10 @@ final class Transform implements MapView.OnMapChangedListener {
private CameraChangeDispatcher cameraChangeDispatcher;
- Transform(NativeMapView mapView, MarkerViewManager markerViewManager, TrackingSettings trackingSettings,
+ Transform(NativeMapView mapView, MarkerViewManager markerViewManager,
CameraChangeDispatcher cameraChangeDispatcher) {
this.mapView = mapView;
this.markerViewManager = markerViewManager;
- this.trackingSettings = trackingSettings;
- this.myLocationView = trackingSettings.getMyLocationView();
this.cameraChangeDispatcher = cameraChangeDispatcher;
}
@@ -73,9 +68,6 @@ final class Transform implements MapView.OnMapChangedListener {
@UiThread
void updateCameraPosition(@NonNull CameraPosition position) {
- if (myLocationView != null) {
- myLocationView.setCameraPosition(position);
- }
markerViewManager.setTilt((float) position.tilt);
}
@@ -103,7 +95,6 @@ final class Transform implements MapView.OnMapChangedListener {
final void moveCamera(MapboxMap mapboxMap, CameraUpdate update, final MapboxMap.CancelableCallback callback) {
CameraPosition cameraPosition = update.getCameraPosition(mapboxMap);
if (isValidCameraPosition(cameraPosition)) {
- trackingSettings.resetTrackingModesIfRequired(this.cameraPosition, cameraPosition, false);
cancelTransitions();
cameraChangeDispatcher.onCameraMoveStarted(OnCameraMoveStartedListener.REASON_API_ANIMATION);
mapView.jumpTo(cameraPosition.bearing, cameraPosition.target, cameraPosition.tilt, cameraPosition.zoom);
@@ -125,7 +116,6 @@ final class Transform implements MapView.OnMapChangedListener {
final MapboxMap.CancelableCallback callback, boolean isDismissable) {
CameraPosition cameraPosition = update.getCameraPosition(mapboxMap);
if (isValidCameraPosition(cameraPosition)) {
- trackingSettings.resetTrackingModesIfRequired(this.cameraPosition, cameraPosition, isDismissable);
cancelTransitions();
cameraChangeDispatcher.onCameraMoveStarted(OnCameraMoveStartedListener.REASON_API_ANIMATION);
@@ -143,7 +133,6 @@ final class Transform implements MapView.OnMapChangedListener {
final MapboxMap.CancelableCallback callback) {
CameraPosition cameraPosition = update.getCameraPosition(mapboxMap);
if (isValidCameraPosition(cameraPosition)) {
- trackingSettings.resetTrackingModesIfRequired(this.cameraPosition, cameraPosition, false);
cancelTransitions();
cameraChangeDispatcher.onCameraMoveStarted(OnCameraMoveStartedListener.REASON_API_ANIMATION);
@@ -237,31 +226,15 @@ final class Transform implements MapView.OnMapChangedListener {
return mapView.getZoom();
}
- void zoomIn(@NonNull PointF focalPoint) {
- CameraPosition cameraPosition = invalidateCameraPosition();
- if (cameraPosition != null) {
- int newZoom = (int) Math.round(cameraPosition.zoom + 1);
- setZoom(newZoom, focalPoint, MapboxConstants.ANIMATION_DURATION);
- }
- }
-
- void zoomOut(@NonNull PointF focalPoint) {
- CameraPosition cameraPosition = invalidateCameraPosition();
- if (cameraPosition != null) {
- int newZoom = (int) Math.round(cameraPosition.zoom - 1);
- setZoom(newZoom, focalPoint, MapboxConstants.ANIMATION_DURATION);
- }
- }
-
void zoomBy(double zoomAddition, @NonNull PointF focalPoint) {
- setZoom(mapView.getZoom() + zoomAddition, focalPoint, 0);
+ setZoom(mapView.getZoom() + zoomAddition, focalPoint);
}
void setZoom(double zoom, @NonNull PointF focalPoint) {
setZoom(zoom, focalPoint, 0);
}
- void setZoom(double zoom, @NonNull PointF focalPoint, long duration) {
+ void setZoom(double zoom, @NonNull PointF focalPoint, final long duration) {
if (mapView != null) {
mapView.addOnMapChangedListener(new MapView.OnMapChangedListener() {
@Override
@@ -297,23 +270,14 @@ final class Transform implements MapView.OnMapChangedListener {
}
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);
}
void setBearing(double bearing, float focalX, float focalY, long duration) {
- if (myLocationView != null) {
- myLocationView.setBearing(bearing);
- }
mapView.setBearing(bearing, focalX, focalY, duration);
}
@@ -335,9 +299,6 @@ final class Transform implements MapView.OnMapChangedListener {
}
void setTilt(Double pitch) {
- if (myLocationView != null) {
- myLocationView.setTilt(pitch);
- }
markerViewManager.setTilt(pitch.floatValue());
mapView.setPitch(pitch, 0);
}
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 2f6110d8b1..c1daebbe52 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
@@ -45,21 +45,23 @@ public final class UiSettings {
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 doubleTapGesturesEnabled = true;
- private boolean doubleTapGestureChangeAllowed = true;
+
+ private boolean scaleVelocityAnimationEnabled = true;
+ private boolean rotateVelocityAnimationEnabled = true;
+ private boolean flingVelocityAnimationEnabled = true;
+
+ private boolean increaseRotateThresholdWhenScaling = true;
+ private boolean increaseScaleThresholdWhenRotating = true;
private boolean deselectMarkersOnTap = true;
@@ -108,42 +110,39 @@ public final class UiSettings {
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());
setDoubleTapGesturesEnabled(options.getDoubleTapGesturesEnabled());
- setDoubleTapGestureChangeAllowed(options.getDoubleTapGesturesEnabled());
}
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());
outState.putBoolean(MapboxConstants.STATE_DOUBLE_TAP_ENABLED, isDoubleTapGesturesEnabled());
- outState.putBoolean(MapboxConstants.STATE_DOUBLE_TAP_ENABLED_CHANGE, isDoubleTapGestureChangeAllowed());
+ outState.putBoolean(MapboxConstants.STATE_SCALE_ANIMATION_ENABLED, isScaleVelocityAnimationEnabled());
+ outState.putBoolean(MapboxConstants.STATE_ROTATE_ANIMATION_ENABLED, isRotateVelocityAnimationEnabled());
+ outState.putBoolean(MapboxConstants.STATE_FLING_ANIMATION_ENABLED, isFlingVelocityAnimationEnabled());
+ outState.putBoolean(MapboxConstants.STATE_INCREASE_ROTATE_THRESHOLD, isIncreaseRotateThresholdWhenScaling());
+ outState.putBoolean(MapboxConstants.STATE_INCREASE_SCALE_THRESHOLD, isIncreaseScaleThresholdWhenRotating());
}
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));
setDoubleTapGesturesEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_DOUBLE_TAP_ENABLED));
- setDoubleTapGestureChangeAllowed(savedInstanceState.getBoolean(MapboxConstants.STATE_DOUBLE_TAP_ENABLED_CHANGE));
+ setScaleVelocityAnimationEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_SCALE_ANIMATION_ENABLED));
+ setRotateVelocityAnimationEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_ROTATE_ANIMATION_ENABLED));
+ setFlingVelocityAnimationEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_FLING_ANIMATION_ENABLED));
+ setIncreaseRotateThresholdWhenScaling(
+ savedInstanceState.getBoolean(MapboxConstants.STATE_INCREASE_ROTATE_THRESHOLD));
+ setIncreaseScaleThresholdWhenRotating(
+ savedInstanceState.getBoolean(MapboxConstants.STATE_INCREASE_SCALE_THRESHOLD));
}
private void initialiseCompass(MapboxMapOptions options, Resources resources) {
@@ -658,9 +657,7 @@ public final class UiSettings {
* @param rotateGesturesEnabled If true, rotating is enabled.
*/
public void setRotateGesturesEnabled(boolean rotateGesturesEnabled) {
- if (rotateGestureChangeAllowed) {
- this.rotateGesturesEnabled = rotateGesturesEnabled;
- }
+ this.rotateGesturesEnabled = rotateGesturesEnabled;
}
/**
@@ -672,14 +669,6 @@ public final class UiSettings {
return rotateGesturesEnabled;
}
- void setRotateGestureChangeAllowed(boolean rotateGestureChangeAllowed) {
- this.rotateGestureChangeAllowed = rotateGestureChangeAllowed;
- }
-
- boolean isRotateGestureChangeAllowed() {
- return rotateGestureChangeAllowed;
- }
-
/**
* <p>
* Changes whether the user may tilt the map.
@@ -693,9 +682,8 @@ public final class UiSettings {
* @param tiltGesturesEnabled If true, tilting is enabled.
*/
public void setTiltGesturesEnabled(boolean tiltGesturesEnabled) {
- if (tiltGestureChangeAllowed) {
- this.tiltGesturesEnabled = tiltGesturesEnabled;
- }
+ this.tiltGesturesEnabled = tiltGesturesEnabled;
+
}
/**
@@ -707,14 +695,6 @@ public final class UiSettings {
return tiltGesturesEnabled;
}
- void setTiltGestureChangeAllowed(boolean tiltGestureChangeAllowed) {
- this.tiltGestureChangeAllowed = tiltGestureChangeAllowed;
- }
-
- boolean isTiltGestureChangeAllowed() {
- return tiltGestureChangeAllowed;
- }
-
/**
* <p>
* Changes whether the user may zoom the map.
@@ -728,9 +708,7 @@ public final class UiSettings {
* @param zoomGesturesEnabled If true, zooming is enabled.
*/
public void setZoomGesturesEnabled(boolean zoomGesturesEnabled) {
- if (zoomGestureChangeAllowed) {
- this.zoomGesturesEnabled = zoomGesturesEnabled;
- }
+ this.zoomGesturesEnabled = zoomGesturesEnabled;
}
/**
@@ -742,14 +720,6 @@ public final class UiSettings {
return zoomGesturesEnabled;
}
- void setZoomGestureChangeAllowed(boolean zoomGestureChangeAllowed) {
- this.zoomGestureChangeAllowed = zoomGestureChangeAllowed;
- }
-
- boolean isZoomGestureChangeAllowed() {
- return zoomGestureChangeAllowed;
- }
-
/**
* <p>
* Sets whether the zoom controls are enabled.
@@ -788,9 +758,7 @@ public final class UiSettings {
* @param doubleTapGesturesEnabled If true, zooming with a double tap is enabled.
*/
public void setDoubleTapGesturesEnabled(boolean doubleTapGesturesEnabled) {
- if (doubleTapGestureChangeAllowed) {
- this.doubleTapGesturesEnabled = doubleTapGesturesEnabled;
- }
+ this.doubleTapGesturesEnabled = doubleTapGesturesEnabled;
}
/**
@@ -802,14 +770,6 @@ public final class UiSettings {
return doubleTapGesturesEnabled;
}
- void setDoubleTapGestureChangeAllowed(boolean doubleTapGestureChangeAllowed) {
- this.doubleTapGestureChangeAllowed = doubleTapGestureChangeAllowed;
- }
-
- boolean isDoubleTapGestureChangeAllowed() {
- return doubleTapGestureChangeAllowed;
- }
-
private void restoreDeselectMarkersOnTap(Bundle savedInstanceState) {
setDeselectMarkersOnTap(savedInstanceState.getBoolean(MapboxConstants.STATE_DESELECT_MARKER_ON_TAP));
}
@@ -851,9 +811,7 @@ public final class UiSettings {
* @param scrollGesturesEnabled If true, scrolling is enabled.
*/
public void setScrollGesturesEnabled(boolean scrollGesturesEnabled) {
- if (scrollGestureChangeAllowed) {
- this.scrollGesturesEnabled = scrollGesturesEnabled;
- }
+ this.scrollGesturesEnabled = scrollGesturesEnabled;
}
/**
@@ -865,12 +823,105 @@ public final class UiSettings {
return scrollGesturesEnabled;
}
- void setScrollGestureChangeAllowed(boolean scrollGestureChangeAllowed) {
- this.scrollGestureChangeAllowed = scrollGestureChangeAllowed;
+ /**
+ * Returns whether scale velocity animation should execute after users finishes a gesture.
+ *
+ * @return If true, scale velocity animation is enabled.
+ */
+ public boolean isScaleVelocityAnimationEnabled() {
+ return scaleVelocityAnimationEnabled;
}
- boolean isScrollGestureChangeAllowed() {
- return scrollGestureChangeAllowed;
+ /**
+ * Set whether scale velocity animation should execute after users finishes a gesture. True by default.
+ *
+ * @param scaleVelocityAnimationEnabled If true, scale velocity animation will be enabled.
+ */
+ public void setScaleVelocityAnimationEnabled(boolean scaleVelocityAnimationEnabled) {
+ this.scaleVelocityAnimationEnabled = scaleVelocityAnimationEnabled;
+ }
+
+ /**
+ * Returns whether rotate velocity animation should execute after users finishes a gesture.
+ *
+ * @return If true, rotate velocity animation is enabled.
+ */
+ public boolean isRotateVelocityAnimationEnabled() {
+ return rotateVelocityAnimationEnabled;
+ }
+
+ /**
+ * Set whether rotate velocity animation should execute after users finishes a gesture. True by default.
+ *
+ * @param rotateVelocityAnimationEnabled If true, rotate velocity animation will be enabled.
+ */
+ public void setRotateVelocityAnimationEnabled(boolean rotateVelocityAnimationEnabled) {
+ this.rotateVelocityAnimationEnabled = rotateVelocityAnimationEnabled;
+ }
+
+ /**
+ * Returns whether fling velocity animation should execute after users finishes a gesture.
+ *
+ * @return If true, fling velocity animation is enabled.
+ */
+ public boolean isFlingVelocityAnimationEnabled() {
+ return flingVelocityAnimationEnabled;
+ }
+
+ /**
+ * Set whether fling velocity animation should execute after users finishes a gesture. True by default.
+ *
+ * @param flingVelocityAnimationEnabled If true, fling velocity animation will be enabled.
+ */
+ public void setFlingVelocityAnimationEnabled(boolean flingVelocityAnimationEnabled) {
+ this.flingVelocityAnimationEnabled = flingVelocityAnimationEnabled;
+ }
+
+ /**
+ * Set whether all velocity animations should execute after users finishes a gesture.
+ *
+ * @param allVelocityAnimationsEnabled If true, all velocity animations will be enabled.
+ */
+ public void setAllVelocityAnimationsEnabled(boolean allVelocityAnimationsEnabled) {
+ setScaleVelocityAnimationEnabled(allVelocityAnimationsEnabled);
+ setRotateVelocityAnimationEnabled(allVelocityAnimationsEnabled);
+ setFlingVelocityAnimationEnabled(allVelocityAnimationsEnabled);
+ }
+
+ /**
+ * Returns whether rotation threshold should be increase whenever scale is detected.
+ *
+ * @return If true, rotation threshold will be increased.
+ */
+ public boolean isIncreaseRotateThresholdWhenScaling() {
+ return increaseRotateThresholdWhenScaling;
+ }
+
+ /**
+ * Set whether rotation threshold should be increase whenever scale is detected.
+ *
+ * @param increaseRotateThresholdWhenScaling If true, rotation threshold will be increased.
+ */
+ public void setIncreaseRotateThresholdWhenScaling(boolean increaseRotateThresholdWhenScaling) {
+ this.increaseRotateThresholdWhenScaling = increaseRotateThresholdWhenScaling;
+ }
+
+ /**
+ * Returns whether scale threshold should be increase whenever rotation is detected.
+ *
+ * @return If true, scale threshold will be increased.
+ */
+ public boolean isIncreaseScaleThresholdWhenRotating() {
+ return increaseScaleThresholdWhenRotating;
+ }
+
+ /**
+ * set whether scale threshold should be increase whenever rotation is detected.
+ *
+ * @param increaseScaleThresholdWhenRotating If true, scale threshold will be increased.
+ */
+ public void setIncreaseScaleThresholdWhenRotating(boolean increaseScaleThresholdWhenRotating) {
+ this.increaseScaleThresholdWhenRotating = increaseScaleThresholdWhenRotating;
}
/**
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/MapRenderer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/MapRenderer.java
index fcee5bd179..f1c70325a0 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/MapRenderer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/MapRenderer.java
@@ -37,11 +37,11 @@ public abstract class MapRenderer implements MapRendererScheduler {
}
public void onPause() {
- // Implement if needed
+ nativeOnPause();
}
public void onResume() {
- // Implement if needed
+ nativeOnResume();
}
public void onStop() {
@@ -124,6 +124,10 @@ public abstract class MapRenderer implements MapRendererScheduler {
private native void nativeRender();
+ private native void nativeOnResume();
+
+ private native void nativeOnPause();
+
private long frames;
private long timeElapsed;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigChooser.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigChooser.java
index 247ffea906..46238ee789 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigChooser.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/EGLConfigChooser.java
@@ -54,6 +54,17 @@ public class EGLConfigChooser implements GLSurfaceView.EGLConfigChooser {
@SuppressWarnings("JavadocReference")
private static final int EGL_OPENGL_ES2_BIT = 0x0004;
+ private boolean translucentSurface;
+
+ public EGLConfigChooser() {
+ this(false);
+ }
+
+ public EGLConfigChooser(boolean translucentSurface) {
+ super();
+ this.translucentSurface = translucentSurface;
+ }
+
@Override
public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
int[] configAttribs = getConfigAttributes();
@@ -274,7 +285,7 @@ public class EGLConfigChooser implements GLSurfaceView.EGLConfigChooser {
EGL_RED_SIZE, 5,
EGL_GREEN_SIZE, 6,
EGL_BLUE_SIZE, 5,
- EGL_ALPHA_SIZE, 0,
+ EGL_ALPHA_SIZE, translucentSurface ? 8 : 0,
EGL_DEPTH_SIZE, 16,
EGL_STENCIL_SIZE, 8,
(emulator ? EGL_NONE : EGL_CONFORMANT), EGL_OPENGL_ES2_BIT,
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/package-info.java
new file mode 100644
index 0000000000..b14b302652
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/egl/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Contains the Mapbox Maps Android EGL API classes.
+ */
+package com.mapbox.mapboxsdk.maps.renderer.egl;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/package-info.java
new file mode 100644
index 0000000000..aefcffef42
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/glsurfaceview/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Contains the Mapbox Maps Android GLSurfaceView API classes.
+ */
+package com.mapbox.mapboxsdk.maps.renderer.glsurfaceview;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/package-info.java
new file mode 100644
index 0000000000..f5d8021ea1
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Contains the Mapbox Maps Android Renderer API classes.
+ */
+package com.mapbox.mapboxsdk.maps.renderer;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewMapRenderer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewMapRenderer.java
index dcc95217ff..ad25dea0d3 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewMapRenderer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewMapRenderer.java
@@ -17,17 +17,22 @@ import javax.microedition.khronos.opengles.GL10;
*/
public class TextureViewMapRenderer extends MapRenderer {
private TextureViewRenderThread renderThread;
+ private boolean translucentSurface;
/**
* Create a {@link MapRenderer} for the given {@link TextureView}
*
- * @param context the current Context
- * @param textureView the TextureView
+ * @param context the current Context
+ * @param textureView the TextureView
+ * @param localIdeographFontFamily the local font family
+ * @param translucentSurface the translucency flag
*/
public TextureViewMapRenderer(@NonNull Context context,
@NonNull TextureView textureView,
- String localIdeographFontFamily) {
+ String localIdeographFontFamily,
+ boolean translucentSurface) {
super(context, localIdeographFontFamily);
+ this.translucentSurface = translucentSurface;
renderThread = new TextureViewRenderThread(textureView, this);
renderThread.start();
}
@@ -95,4 +100,8 @@ public class TextureViewMapRenderer extends MapRenderer {
public void onDestroy() {
renderThread.onDestroy();
}
+
+ public boolean isTranslucentSurface() {
+ return translucentSurface;
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java
index 1e76ffe3fb..4bba160993 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/TextureViewRenderThread.java
@@ -53,9 +53,10 @@ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextu
*/
@UiThread
TextureViewRenderThread(@NonNull TextureView textureView, @NonNull TextureViewMapRenderer mapRenderer) {
+ textureView.setOpaque(!mapRenderer.isTranslucentSurface());
textureView.setSurfaceTextureListener(this);
this.mapRenderer = mapRenderer;
- this.eglHolder = new EGLHolder(new WeakReference<>(textureView));
+ this.eglHolder = new EGLHolder(new WeakReference<>(textureView), mapRenderer.isTranslucentSurface());
}
// SurfaceTextureListener methods
@@ -324,6 +325,7 @@ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextu
private static class EGLHolder {
private static final int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
private final WeakReference<TextureView> textureViewWeakRef;
+ private boolean translucentSurface;
private EGL10 egl;
private EGLConfig eglConfig;
@@ -331,8 +333,9 @@ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextu
private EGLContext eglContext = EGL10.EGL_NO_CONTEXT;
private EGLSurface eglSurface = EGL10.EGL_NO_SURFACE;
- EGLHolder(WeakReference<TextureView> textureViewWeakRef) {
+ EGLHolder(WeakReference<TextureView> textureViewWeakRef, boolean translucentSurface) {
this.textureViewWeakRef = textureViewWeakRef;
+ this.translucentSurface = translucentSurface;
}
void prepare() {
@@ -357,7 +360,7 @@ class TextureViewRenderThread extends Thread implements TextureView.SurfaceTextu
eglConfig = null;
eglContext = EGL10.EGL_NO_CONTEXT;
} else if (eglContext == EGL10.EGL_NO_CONTEXT) {
- eglConfig = new EGLConfigChooser().chooseConfig(egl, eglDisplay);
+ eglConfig = new EGLConfigChooser(translucentSurface).chooseConfig(egl, eglDisplay);
int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE};
eglContext = egl.eglCreateContext(eglDisplay, eglConfig, EGL10.EGL_NO_CONTEXT, attrib_list);
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/package-info.java
new file mode 100644
index 0000000000..d3585d41f9
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/renderer/textureview/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Contains the Mapbox Maps Android TextureView API classes.
+ */
+package com.mapbox.mapboxsdk.maps.renderer.textureview;
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 45f72af1c5..fb2c70cb73 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
@@ -1,15 +1,16 @@
package com.mapbox.mapboxsdk.maps.widgets;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.annotation.NonNull;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.ViewPropertyAnimatorCompat;
import android.support.v4.view.ViewPropertyAnimatorListenerAdapter;
-import android.support.v7.widget.AppCompatImageView;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.ImageView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
@@ -22,7 +23,8 @@ import com.mapbox.mapboxsdk.maps.MapboxMap;
* use {@link com.mapbox.mapboxsdk.maps.UiSettings}.
* </p>
*/
-public final class CompassView extends AppCompatImageView implements Runnable {
+@SuppressLint("AppCompatCustomView")
+public final class CompassView extends ImageView implements Runnable {
public static final long TIME_WAIT_IDLE = 500;
public static final long TIME_MAP_NORTH_ANIMATION = 150;
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
deleted file mode 100644
index 3f37da99d5..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationView.java
+++ /dev/null
@@ -1,1104 +0,0 @@
-package com.mapbox.mapboxsdk.maps.widgets;
-
-import android.animation.ValueAnimator;
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.graphics.Camera;
-import android.graphics.Canvas;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.PointF;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.location.Location;
-import android.os.Bundle;
-import android.os.Parcelable;
-import android.os.SystemClock;
-import android.support.annotation.ColorInt;
-import android.support.annotation.FloatRange;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-
-import com.mapbox.mapboxsdk.Mapbox;
-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.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.Projection;
-import com.mapbox.android.core.location.LocationEngine;
-import com.mapbox.android.core.location.LocationEngineListener;
-import com.mapbox.android.core.location.LocationEnginePriority;
-
-import java.lang.ref.WeakReference;
-
-import timber.log.Timber;
-
-/**
- * UI element overlaid on a map to show the user's location.
- * <p>
- * Use {@link MyLocationViewSettings} to manipulate the state of this view.
- * </p>
- *
- * @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugins/locationlayer instead.
- */
-@Deprecated
-public class MyLocationView extends View {
-
- private static final int UNDEFINED_TINT_COLOR = -1;
- private MyLocationBehavior myLocationBehavior;
- private MapboxMap mapboxMap;
-
- private Projection projection;
- private float[] projectedCoordinate = new float[2];
- private float projectedX;
- private float projectedY;
-
- private float contentPaddingX;
- private float contentPaddingY;
-
- private LatLng latLng;
- private Location location;
- private LocationEngine locationEngine;
- private long locationUpdateTimestamp;
- private float previousDirection;
-
- private float accuracy;
- private Paint accuracyPaint;
- private float accuracyThreshold;
-
- private ValueAnimator locationChangeAnimator;
- private ValueAnimator accuracyAnimator;
- private ValueAnimator directionAnimator;
- private boolean locationChangeAnimationEnabled = true;
-
- private ValueAnimator.AnimatorUpdateListener invalidateSelfOnUpdateListener =
- new ValueAnimator.AnimatorUpdateListener() {
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- invalidate();
- }
- };
-
- private Drawable foregroundDrawable;
- private Drawable foregroundBearingDrawable;
- private Drawable backgroundDrawable;
-
- private Rect foregroundBounds;
- private Rect backgroundBounds;
-
- private int backgroundOffsetLeft;
- private int backgroundOffsetTop;
- private int backgroundOffsetRight;
- private int backgroundOffsetBottom;
-
- private Matrix matrix;
- private Camera camera;
- private PointF screenLocation;
-
- // camera vars
- private double tilt;
- private double bearing;
- private float magneticHeading;
-
- // Controls the compass update rate in milliseconds
- private static final int COMPASS_UPDATE_RATE_MS = 500;
-
- @MyLocationTracking.Mode
- private int myLocationTrackingMode;
-
- @MyBearingTracking.Mode
- private int myBearingTrackingMode;
-
- private GpsLocationListener userLocationListener;
- private CompassListener compassListener;
-
- 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;
- }
-
- setEnabled(false);
-
- // setup LayoutParams
- ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(
- ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.MATCH_PARENT);
- setLayoutParams(lp);
-
- matrix = new Matrix();
- camera = new Camera();
- camera.setLocation(0, 0, -1000);
- accuracyPaint = new Paint();
-
- myLocationBehavior = new MyLocationBehaviorFactory().getBehavioralModel(MyLocationTracking.TRACKING_NONE);
- compassListener = new CompassListener(context);
- }
-
- @Deprecated
- public void init(LocationEngine locationSource) {
- this.locationEngine = locationSource;
- }
-
- /**
- * Set the foreground drawable, for internal use only.
- *
- * @param defaultDrawable The drawable shown when showing this view
- * @param bearingDrawable The drawable shown when tracking of bearing is enabled
- */
- public final void setForegroundDrawables(Drawable defaultDrawable, Drawable bearingDrawable) {
- if (defaultDrawable == null) {
- return;
- }
-
- if (bearingDrawable == null) {
- // if user only provided one resource
- // use same for bearing mode
- bearingDrawable = defaultDrawable.getConstantState().newDrawable();
- }
-
- 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();
- }
-
- if (defaultDrawable.getIntrinsicWidth() != bearingDrawable.getIntrinsicWidth()
- || defaultDrawable.getIntrinsicHeight() != bearingDrawable.getIntrinsicHeight()) {
- throw new RuntimeException("The dimensions from location and bearing drawables should be match");
- }
-
- foregroundDrawable = defaultDrawable;
- foregroundBearingDrawable = bearingDrawable;
-
- invalidateBounds();
- }
-
- /**
- * Set the foreground drawable tint, for internal use only.
- *
- * @param color The color to tint the drawable with
- */
- public final void setForegroundDrawableTint(@ColorInt int color) {
- applyDrawableTint(foregroundDrawable, color);
- applyDrawableTint(foregroundBearingDrawable, color);
- invalidate();
- }
-
- /**
- * Set the shadow drawable, for internal use only.
- *
- * @param drawable The drawable shown as shadow
- */
- public final void setShadowDrawable(Drawable drawable) {
- setShadowDrawable(drawable, 0, 0, 0, 0);
- }
-
- /**
- * Set the shadow drawable with some additional offset.
- *
- * @param drawable The drawable shown as shadow
- * @param left The left offset margin
- * @param top The top offset margin
- * @param right The right offset margin
- * @param bottom The bottom offset margin
- */
- public final void setShadowDrawable(Drawable drawable, int left, int top, int right, int bottom) {
- if (drawable != null) {
- backgroundDrawable = drawable;
- }
-
- backgroundOffsetLeft = left;
- backgroundOffsetTop = top;
- backgroundOffsetRight = right;
- backgroundOffsetBottom = bottom;
-
- invalidateBounds();
- }
-
- /**
- * Set the shadow drawable tint color, for internal use only.
- *
- * @param color The tint color to apply
- */
- public final void setShadowDrawableTint(@ColorInt int color) {
- if (backgroundDrawable == null) {
- return;
- }
- applyDrawableTint(backgroundDrawable, color);
- invalidate();
- }
-
- /**
- * Set the accuracy tint color, for internal use only.
- *
- * @param color The tint color to apply
- */
- public final void setAccuracyTint(@ColorInt int color) {
- int alpha = accuracyPaint.getAlpha();
- accuracyPaint.setColor(color);
- accuracyPaint.setAlpha(alpha);
- invalidate();
- }
-
- /**
- * Set the accuracy alpha value, for internal use only.
- *
- * @param alpha The alpha accuracy value to apply
- */
- 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;
- }
-
- 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);
-
- 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);
-
- // invoke a new draw
- invalidate();
- }
-
- @Override
- protected void onDraw(Canvas canvas) {
- super.onDraw(canvas);
-
- if (location == null || foregroundBounds == null || backgroundBounds == null || accuracyAnimator == null
- || screenLocation == null) {
- // Not ready yet
- return;
- }
-
- final PointF pointF = screenLocation;
- float metersPerPixel = (float) projection.getMetersPerPixelAtLatitude(location.getLatitude());
- float accuracyPixels = (Float) accuracyAnimator.getAnimatedValue() / metersPerPixel;
-
- // reset
- matrix.reset();
- projectedCoordinate[0] = 0;
- projectedCoordinate[1] = 0;
-
- // put camera in position
- camera.save();
- camera.rotate((float) tilt, 0, 0);
- camera.getMatrix(matrix);
-
- if (myBearingTrackingMode != MyBearingTracking.NONE && directionAnimator != null) {
- matrix.preRotate((Float) directionAnimator.getAnimatedValue());
- }
-
- matrix.preTranslate(0, contentPaddingY);
- matrix.postTranslate(pointF.x, pointF.y - contentPaddingY);
-
- // concat our matrix on canvas
- canvas.concat(matrix);
-
- // calculate focal point
- matrix.mapPoints(projectedCoordinate);
- projectedX = pointF.x - projectedCoordinate[0];
- projectedY = pointF.y - projectedCoordinate[1];
-
- // restore orientation from camera
- camera.restore();
-
- // draw circle
- canvas.drawCircle(0, 0, accuracyPixels, accuracyPaint);
-
- // draw shadow
- if (backgroundDrawable != null) {
- backgroundDrawable.draw(canvas);
- }
-
- // draw foreground
- if (myBearingTrackingMode == MyBearingTracking.NONE) {
- if (foregroundDrawable != null) {
- foregroundDrawable.draw(canvas);
- }
- } else if (foregroundBearingDrawable != null && foregroundBounds != null) {
- if (myBearingTrackingMode == MyBearingTracking.GPS
- || myBearingTrackingMode == MyBearingTracking.GPS_NORTH_FACING
- || compassListener.isSensorAvailable()) {
- foregroundBearingDrawable.draw(canvas);
- } else {
- // We are tracking MyBearingTracking.COMPASS, but sensor is not available.
- foregroundDrawable.draw(canvas);
- }
- }
- }
-
- /**
- * Set the tilt value, for internal use only.
- *
- * @param tilt The tilt to apply
- */
- public void setTilt(@FloatRange(from = 0, to = 60.0f) double tilt) {
- this.tilt = tilt;
- invalidate();
- }
-
- /**
- * Set the bearing value, for internal use only.
- *
- * @param bearing The bearing to apply
- */
- public void setBearing(double bearing) {
- this.bearing = bearing;
- if (myLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
- if (myBearingTrackingMode == MyBearingTracking.GPS
- || myBearingTrackingMode == MyBearingTracking.GPS_NORTH_FACING) {
- if (location != null) {
- setCompass(location.getBearing() - bearing);
- }
- } else if (myBearingTrackingMode == MyBearingTracking.COMPASS && compassListener.isSensorAvailable()) {
- setCompass(magneticHeading - bearing);
- }
- }
- }
-
- /**
- * Set the bearing and tilt from a camera position, for internal use only.
- *
- * @param position The camera position to extract bearing and tilt from
- */
- public void setCameraPosition(CameraPosition position) {
- if (position != null) {
- setBearing(position.bearing);
- setTilt(position.tilt);
- }
- }
-
- /**
- * Called when the hosting activity is starting, for internal use only.
- */
- public void onStart() {
- if (myBearingTrackingMode == MyBearingTracking.COMPASS && compassListener.isSensorAvailable()) {
- compassListener.onResume();
- }
- if (isEnabled()) {
- toggleGps(true);
- }
- }
-
- /**
- * Called when the hosting activity is stopping, for internal use only.
- */
- 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;
- }
-
- if (accuracyAnimator != null) {
- accuracyAnimator.cancel();
- accuracyAnimator = null;
- }
-
- if (directionAnimator != null) {
- directionAnimator.cancel();
- directionAnimator = null;
- }
-
- if (userLocationListener != null) {
- locationEngine.removeLocationEngineListener(userLocationListener);
- locationEngine = null;
- userLocationListener = null;
- }
- }
-
- /**
- * Update current locationstate.
- */
- 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();
- }
-
- /**
- * Set the enabled state, for internal use only.
- *
- * @param enabled The value to set the state to
- */
- @Override
- public void setEnabled(boolean enabled) {
- setEnabled(enabled, false);
- }
-
- /**
- * Set the enabled state, for internal use only.
- *
- * @param enabled The value to set the state to
- * @param isCustomLocationEngine Flag handling for handling user provided custom location engine
- */
- public void setEnabled(boolean enabled, boolean isCustomLocationEngine) {
- super.setEnabled(enabled);
- setVisibility(enabled ? View.VISIBLE : View.INVISIBLE);
- toggleGps(enabled, isCustomLocationEngine);
- }
-
- /**
- * Save the view instance state, for internal use only.
- *
- * @return the marshaled representation of the view state
- */
- @Override
- protected Parcelable onSaveInstanceState() {
- Bundle bundle = new Bundle();
- bundle.putParcelable("superState", super.onSaveInstanceState());
- bundle.putDouble("tilt", tilt);
- return bundle;
- }
-
- /**
- * Restore the view instance state, for internal use only.
- *
- * @param state the marshalled representation of the state to restore
- */
- @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);
- }
-
- private void toggleGps(boolean enableGps) {
- toggleGps(enableGps, mapboxMap != null
- && mapboxMap.getTrackingSettings().isCustomLocationSource());
- }
-
- /**
- * Enabled / Disable GPS location updates along with updating the UI, for internal use only.
- *
- * @param enableGps true if GPS is to be enabled, false if GPS is to be disabled
- */
- private void toggleGps(boolean enableGps, boolean isCustomLocationEngine) {
- if (enableGps) {
- if (locationEngine == null) {
- if (!isCustomLocationEngine) {
- locationEngine = Mapbox.getLocationEngine();
- } else {
- return;
- }
- }
-
- if (userLocationListener == null) {
- userLocationListener = new GpsLocationListener(this, locationEngine);
- }
-
- locationEngine.addLocationEngineListener(userLocationListener);
- locationEngine.setPriority(LocationEnginePriority.HIGH_ACCURACY);
- locationEngine.activate();
- } else {
- if (locationEngine == null) {
- return;
- }
- // Disable location and user dot
- location = null;
- locationEngine.removeLocationEngineListener(userLocationListener);
- locationEngine.removeLocationUpdates();
- locationEngine.deactivate();
- restoreLocationEngine();
- }
- }
-
- /**
- * Get the current location.
- *
- * @return the current location
- */
- public Location getLocation() {
- return location;
- }
-
- /**
- * Set the current location, for internal use only.
- *
- * @param location The current location
- */
- public void setLocation(Location location) {
- if (location == null) {
- this.location = null;
- return;
- }
-
- this.location = location;
- myLocationBehavior.updateLatLng(location);
-
- if (mapboxMap != null && (myBearingTrackingMode == MyBearingTracking.GPS
- || myBearingTrackingMode == MyBearingTracking.GPS_NORTH_FACING)
- && myLocationTrackingMode == MyLocationTracking.TRACKING_NONE) {
- setBearing(mapboxMap.getCameraPosition().bearing);
- }
- }
-
- /**
- * Set location change animation enabled, for internal use only.
- *
- * @param locationChangeAnimationEnabled True if location changes are animated
- */
- public void setLocationChangeAnimationEnabled(boolean locationChangeAnimationEnabled) {
- this.locationChangeAnimationEnabled = locationChangeAnimationEnabled;
- }
-
- /**
- * Set accuracy circle threshold. Circle won't be displayed if accuracy is below set value.
- * For internal use only.
- *
- * @param accuracyThreshold Value below which circle won't be displayed
- */
- public void setAccuracyThreshold(float accuracyThreshold) {
- this.accuracyThreshold = accuracyThreshold;
- }
-
- /**
- * Set the bearing tracking mode, for internal use only.
- *
- * @param myBearingTrackingMode The bearing tracking mode
- */
- public void setMyBearingTrackingMode(@MyBearingTracking.Mode int myBearingTrackingMode) {
- this.myBearingTrackingMode = myBearingTrackingMode;
- if (myBearingTrackingMode == MyBearingTracking.COMPASS && compassListener.isSensorAvailable()) {
- compassListener.onResume();
- } else {
- compassListener.onPause();
- if (myLocationTrackingMode == MyLocationTracking.TRACKING_FOLLOW
- && myBearingTrackingMode == MyBearingTracking.GPS) {
- // always face north
- setCompass(0);
- } else {
- myLocationBehavior.invalidate();
- }
- }
- invalidate();
- }
-
- /**
- * Set the location tracking mode, for internla use only.
- *
- * @param myLocationTrackingMode The location tracking mode
- */
- 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.moveCamera(CameraUpdateFactory.newLatLng(new LatLng(location)));
- } else {
- // do not use interpolated location from tracking mode
- latLng = null;
- }
- myLocationBehavior.updateLatLng(location);
- }
-
- this.myLocationTrackingMode = myLocationTrackingMode;
- invalidate();
- }
-
- /**
- * Get the location tracking mode, for internal use only.
- *
- * @return The location tracking mode
- */
- @MyLocationTracking.Mode
- public int getMyLocationTrackingMode() {
- return myLocationTrackingMode;
- }
-
-
- /**
- * Get the bearing tracking mode, for internal use only.
- *
- * @return the bearing tracking mode
- */
- @MyBearingTracking.Mode
- public int getMyBearingTrackingMode() {
- return myBearingTrackingMode;
- }
-
- /**
- * Set the compass bearing value, for internal use only.
- *
- * @param bearing The compas bearing value
- */
- 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;
-
- directionAnimator = ValueAnimator.ofFloat(oldDir, newDir);
- directionAnimator.setDuration(duration);
- directionAnimator.addUpdateListener(invalidateSelfOnUpdateListener);
- directionAnimator.start();
- }
-
- /**
- * Get the center of this view in screen coordinates.
- *
- * @return the center of the view
- */
- public PointF getCenter() {
- return new PointF(getCenterX(), getCenterY());
- }
-
- /**
- * Get the x value of the center of this view.
- *
- * @return the x value of the center of the view
- */
- private float getCenterX() {
- return (getX() + getMeasuredWidth()) / 2 + contentPaddingX - projectedX;
- }
-
- /**
- * Get the y value of the center of this view.
- *
- * @return the y value of the center of the view
- */
- private 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;
- }
-
- /**
- * Set the location source from which location updates are received, for internal use only.
- *
- * @param locationEngine The location engine to receive updates from
- */
- public void setLocationSource(LocationEngine locationEngine) {
- toggleGps(false);
- this.locationEngine = locationEngine;
- this.userLocationListener = null;
- setEnabled(isEnabled(), locationEngine != null);
- }
-
- private void applyDrawableTint(Drawable drawable, @ColorInt int color) {
- if (color == UNDEFINED_TINT_COLOR) {
- removeTintColorFilter(drawable);
- } else {
- applyTintColorFilter(drawable, color);
- }
- }
-
- private void removeTintColorFilter(Drawable drawable) {
- if (drawable != null) {
- drawable.mutate().setColorFilter(null);
- }
- }
-
- private void applyTintColorFilter(Drawable drawable, @ColorInt int color) {
- if (drawable != null) {
- drawable.mutate().setColorFilter(color, PorterDuff.Mode.SRC_IN);
- }
- }
-
- private void restoreLocationEngine() {
- locationEngine.setPriority(LocationEnginePriority.LOW_POWER);
- locationEngine.activate();
- }
-
- private static class GpsLocationListener implements LocationEngineListener {
-
- private WeakReference<MyLocationView> userLocationView;
- private WeakReference<LocationEngine> locationSource;
-
- GpsLocationListener(MyLocationView myLocationView, LocationEngine locationEngine) {
- userLocationView = new WeakReference<>(myLocationView);
- locationSource = new WeakReference<>(locationEngine);
- }
-
- @SuppressLint("MissingPermission")
- @Override
- public void onConnected() {
- MyLocationView locationView = userLocationView.get();
- LocationEngine locationEngine = locationSource.get();
- if (locationView != null && locationEngine != null) {
- Location lastKnownLocation = locationEngine.getLastLocation();
- if (lastKnownLocation != null) {
- locationView.setLocation(lastKnownLocation);
- }
- locationEngine.requestLocationUpdates();
- }
- }
-
- /**
- * 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 class CompassListener implements SensorEventListener {
-
- private final SensorManager sensorManager;
-
- private Sensor rotationVectorSensor;
- private float[] matrix = new float[9];
- private float[] rotationVectorValue;
- private float[] truncatedRotationVectorValue = new float[4];
-
- private float[] orientation = new float[3];
- private boolean reportMissingSensor = true;
- // 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);
- }
-
- public boolean isSensorAvailable() {
- if (rotationVectorSensor == null && reportMissingSensor) {
- reportMissingSensor = false;
- Timber.e("Sensor.TYPE_ROTATION_VECTOR is missing from this device. Unable to use MyBearingTracking.COMPASS.");
- }
- return rotationVectorSensor != null;
- }
-
- @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) {
- rotationVectorValue = getRotationVectorFromSensorEvent(event);
- SensorManager.getRotationMatrixFromVector(matrix, rotationVectorValue);
- SensorManager.getOrientation(matrix, orientation);
-
- 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);
- }
-
- compassUpdateNextTimestamp = currentTime + COMPASS_UPDATE_RATE_MS;
- }
- }
-
- /**
- * Pulls out the rotation vector from a SensorEvent, with a maximum length
- * vector of four elements to avoid potential compatibility issues.
- *
- * @param event the sensor event
- * @return the events rotation vector, potentially truncated
- */
- @NonNull
- float[] getRotationVectorFromSensorEvent(@NonNull SensorEvent event) {
- if (event.values.length > 4) {
- // On some Samsung devices SensorManager.getRotationMatrixFromVector
- // appears to throw an exception if rotation vector has length > 4.
- // For the purposes of this class the first 4 values of the
- // rotation vector are sufficient (see crbug.com/335298 for details).
- // Only affects Android 4.3
- System.arraycopy(event.values, 0, truncatedRotationVectorValue, 0, 4);
- return truncatedRotationVectorValue;
- } else {
- return event.values;
- }
- }
-
- 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*/, null);
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- }
-
- }
-
- private class MarkerCoordinateAnimatorListener implements ValueAnimator.AnimatorUpdateListener {
-
- private MyLocationBehavior behavior;
- private double fromLat;
- private double fromLng;
- private double toLat;
- private double toLng;
-
- private MarkerCoordinateAnimatorListener(MyLocationBehavior myLocationBehavior, LatLng from, LatLng to) {
- behavior = myLocationBehavior;
- fromLat = from.getLatitude();
- fromLng = from.getLongitude();
- toLat = to.getLatitude();
- toLng = to.getLongitude();
- }
-
- @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();
- }
- }
-
- private class MyLocationBehaviorFactory {
-
- MyLocationBehavior getBehavioralModel(@MyLocationTracking.Mode int mode) {
- if (mode == MyLocationTracking.TRACKING_NONE) {
- return new MyLocationShowBehavior();
- } else {
- return new MyLocationTrackingBehavior();
- }
- }
- }
-
- private abstract class MyLocationBehavior {
-
- MyLocationBehavior() {
- if (latLng != null) {
- locationUpdateTimestamp = SystemClock.elapsedRealtime();
- }
- }
-
- void updateLatLng(@NonNull Location newLocation) {
- location = newLocation;
- }
-
- void updateLatLng(double lat, double lon) {
- if (latLng != null) {
- latLng.setLatitude(lat);
- latLng.setLongitude(lon);
- }
- }
-
- void updateAccuracy(@NonNull Location location) {
- if (accuracyAnimator != null && accuracyAnimator.isRunning()) {
- // use current accuracy as a starting point
- accuracy = (Float) accuracyAnimator.getAnimatedValue();
- accuracyAnimator.end();
- }
-
- float newAccuracy = location.getAccuracy() >= accuracyThreshold ? location.getAccuracy() : 0f;
- accuracyAnimator = ValueAnimator.ofFloat(accuracy, newAccuracy);
- accuracyAnimator.setDuration(750);
- accuracyAnimator.start();
- accuracy = newAccuracy;
- }
-
- 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
- int animationDuration;
- if (previousUpdateTimeStamp == 0) {
- animationDuration = 0;
- } else {
- animationDuration = (int) ((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);
- }
-
- if (myBearingTrackingMode == MyBearingTracking.GPS_NORTH_FACING) {
- builder.bearing(0);
- if (location.hasBearing()) {
- setCompass(location.getBearing(), COMPASS_UPDATE_RATE_MS);
- }
- }
-
- // accuracy
- updateAccuracy(location);
-
- if (locationChangeAnimationEnabled && animationDuration > 0) {
- // ease to new camera position with a linear interpolator
- mapboxMap.easeCamera(CameraUpdateFactory.newCameraPosition(builder.build()), animationDuration, false, null,
- true);
- } else {
- mapboxMap.moveCamera(CameraUpdateFactory.newCameraPosition(builder.build()));
- }
- }
-
- @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();
- }
- }
-
- 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 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);
- if (locationChangeAnimationEnabled) {
- locationChangeAnimator.setDuration(locationUpdateDuration);
- } else {
- locationChangeAnimator.setDuration(0);
- }
- locationChangeAnimator.addUpdateListener(new MarkerCoordinateAnimatorListener(this,
- latLng, newLocation
- ));
- locationChangeAnimator.start();
- latLng = newLocation;
- }
-
- @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
deleted file mode 100644
index ec7c53e1d0..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettings.java
+++ /dev/null
@@ -1,389 +0,0 @@
-package com.mapbox.mapboxsdk.maps.widgets;
-
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.support.annotation.ColorInt;
-import android.support.annotation.IntRange;
-import android.support.annotation.NonNull;
-
-import com.mapbox.mapboxsdk.camera.CameraPosition;
-import com.mapbox.mapboxsdk.constants.MapboxConstants;
-import com.mapbox.mapboxsdk.constants.MyLocationTracking;
-import com.mapbox.mapboxsdk.maps.FocalPointChangeListener;
-import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
-import com.mapbox.mapboxsdk.maps.Projection;
-import com.mapbox.mapboxsdk.utils.BitmapUtils;
-
-/**
- * Settings to configure the visual appearance of the MyLocationView.
- *
- * @deprecated use location layer plugin from
- * https://github.com/mapbox/mapbox-plugins-android/tree/master/plugins/locationlayer instead.
- */
-@Deprecated
-public class MyLocationViewSettings {
-
- private Projection projection;
- private MyLocationView myLocationView;
- private FocalPointChangeListener focalPointChangeListener;
-
- //
- // State
- //
-
- private boolean enabled;
-
- //
- // Foreground
- //
-
- private Drawable foregroundDrawable;
- private Drawable foregroundBearingDrawable;
-
- @ColorInt
- private int foregroundTintColor;
-
- //
- // Background
- //
-
- private Drawable backgroundDrawable;
- private int[] backgroundOffset = new int[4];
-
- @ColorInt
- private int backgroundTintColor;
-
- //
- // Accuracy
- //
-
- private int accuracyAlpha;
- private float accuracyThreshold = 0f;
-
- @ColorInt
- private int accuracyTintColor;
-
- //
- // Padding
- //
-
- private int[] padding = new int[4];
-
- /**
- * 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;
- }
-
- /**
- * Initialise this with MapboxMapOptions.
- *
- * @param options the options to initialise this class from
- */
- public void initialise(@NonNull MapboxMapOptions options) {
- CameraPosition position = options.getCamera();
- if (position != null && !position.equals(CameraPosition.DEFAULT)) {
- setTilt(position.tilt);
- }
- setForegroundDrawable(options.getMyLocationForegroundDrawable(), options.getMyLocationForegroundBearingDrawable());
- setForegroundTintColor(options.getMyLocationForegroundTintColor());
- setBackgroundDrawable(options.getMyLocationBackgroundDrawable(), options.getMyLocationBackgroundPadding());
- setBackgroundTintColor(options.getMyLocationBackgroundTintColor());
- setAccuracyAlpha(options.getMyLocationAccuracyAlpha());
- setAccuracyTintColor(options.getMyLocationAccuracyTintColor());
- setAccuracyThreshold(options.getMyLocationAccuracyThreshold());
- }
-
- public void onSaveInstanceState(Bundle outState) {
- outState.putBoolean(MapboxConstants.STATE_LOCATION_VIEW_ENABLED, isEnabled());
- outState.putByteArray(
- MapboxConstants.STATE_LOCATION_VIEW_FOREGROUND_DRAWABLE,
- BitmapUtils.getByteArrayFromDrawable(getForegroundDrawable())
- );
- outState.putByteArray(
- MapboxConstants.STATE_LOCATION_VIEW_FOREGROUND_BEARING_DRAWABLE,
- BitmapUtils.getByteArrayFromDrawable(getForegroundBearingDrawable())
- );
- outState.putInt(MapboxConstants.STATE_LOCATION_VIEW_FOREGROUND_TINT_COLOR, getForegroundTintColor());
- outState.putByteArray(
- MapboxConstants.STATE_LOCATION_VIEW_BACKGROUND_DRAWABLE,
- BitmapUtils.getByteArrayFromDrawable(getBackgroundDrawable())
- );
- outState.putIntArray(MapboxConstants.STATE_LOCATION_VIEW_BACKGROUND_OFFSET, getBackgroundOffset());
- outState.putInt(MapboxConstants.STATE_LOCATION_VIEW_BACKGROUND_TINT_COLOR, getBackgroundTintColor());
- outState.putInt(MapboxConstants.STATE_LOCATION_VIEW_ACCURACY_ALPHA, getAccuracyAlpha());
- outState.putInt(MapboxConstants.STATE_LOCATION_VIEW_ACCURACY_TINT_COLOR, getAccuracyTintColor());
- outState.putFloat(MapboxConstants.STATE_LOCATION_VIEW_ACCURACY_THRESHOLD, getAccuracyThreshold());
- outState.putIntArray(MapboxConstants.STATE_LOCATION_VIEW_PADDING, getPadding());
- }
-
- public void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
- setEnabled(savedInstanceState.getBoolean(MapboxConstants.STATE_LOCATION_VIEW_ENABLED));
- setForegroundDrawable(
- BitmapUtils.getDrawableFromByteArray(
- myLocationView.getContext(),
- savedInstanceState.getByteArray(MapboxConstants.STATE_LOCATION_VIEW_FOREGROUND_DRAWABLE)
- ),
- BitmapUtils.getDrawableFromByteArray(
- myLocationView.getContext(),
- savedInstanceState.getByteArray(MapboxConstants.STATE_LOCATION_VIEW_FOREGROUND_BEARING_DRAWABLE)
- )
- );
- setForegroundTintColor(savedInstanceState.getInt(MapboxConstants.STATE_LOCATION_VIEW_FOREGROUND_TINT_COLOR));
- setBackgroundDrawable(
- BitmapUtils.getDrawableFromByteArray(
- myLocationView.getContext(),
- savedInstanceState.getByteArray(MapboxConstants.STATE_LOCATION_VIEW_BACKGROUND_DRAWABLE)
- ),
- savedInstanceState.getIntArray(MapboxConstants.STATE_LOCATION_VIEW_BACKGROUND_OFFSET)
- );
- setBackgroundTintColor(savedInstanceState.getInt(MapboxConstants.STATE_LOCATION_VIEW_BACKGROUND_TINT_COLOR));
- setAccuracyAlpha(savedInstanceState.getInt(MapboxConstants.STATE_LOCATION_VIEW_ACCURACY_ALPHA));
- setAccuracyTintColor(savedInstanceState.getInt(MapboxConstants.STATE_LOCATION_VIEW_ACCURACY_TINT_COLOR));
- setAccuracyThreshold(savedInstanceState.getFloat(MapboxConstants.STATE_LOCATION_VIEW_ACCURACY_THRESHOLD));
- setPadding(savedInstanceState.getIntArray(MapboxConstants.STATE_LOCATION_VIEW_PADDING));
- }
-
- /**
- * 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>
- * It's linked with the foreground tint color
- *
- * @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);
- myLocationView.setForegroundDrawableTint(foregroundTintColor);
- }
-
- /**
- * 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 or -1 (undefined color) to remove the
- * existing foreground tint color
- */
- 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>
- * It's linked with the background tint color
- *
- * @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);
- }
- myLocationView.setShadowDrawableTint(backgroundTintColor);
- }
-
- /**
- * 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 drawable or -1 (undefined color) to remove the
- * existing background tint color
- */
- 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};
- setPadding(padding);
- }
-
- private void setPadding(int[] padding) {
- 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);
- }
-
- /**
- * Returns current accuracy threshold value (in meters).
- *
- * @return Value of accuracy threshold (in meters), below which circle won't be displayed
- */
- public float getAccuracyThreshold() {
- return accuracyThreshold;
- }
-
- /**
- * Set accuracy circle threshold. Circle won't be displayed if accuracy is below set value.
- *
- * @param accuracyThreshold Value of accuracy (in meters), below which circle won't be displayed
- */
- public void setAccuracyThreshold(float accuracyThreshold) {
- this.accuracyThreshold = accuracyThreshold;
- myLocationView.setAccuracyThreshold(accuracyThreshold);
- }
-
- public void setTilt(double tilt) {
- myLocationView.setTilt(tilt);
- }
-
- private void invalidateFocalPointForTracking(MyLocationView myLocationView) {
- if (!(myLocationView.getMyLocationTrackingMode() == MyLocationTracking.TRACKING_NONE)) {
- focalPointChangeListener.onFocalPointChanged(myLocationView.getCenter());
- } else {
- focalPointChangeListener.onFocalPointChanged(null);
- }
- }
-}
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 090e9576ee..946d3694d5 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
@@ -5,7 +5,6 @@ import android.os.Looper;
import android.support.annotation.IntDef;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
-
import com.mapbox.mapboxsdk.LibraryLoader;
import com.mapbox.mapboxsdk.Mapbox;
import com.mapbox.mapboxsdk.storage.FileSource;
@@ -250,9 +249,12 @@ public class OfflineRegion {
@Override
public void onStatusChanged(final OfflineRegionStatus status) {
if (deliverMessages()) {
- handler.post(() -> {
- if (observer != null) {
- observer.onStatusChanged(status);
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (observer != null) {
+ observer.onStatusChanged(status);
+ }
}
});
}
@@ -261,9 +263,12 @@ public class OfflineRegion {
@Override
public void onError(final OfflineRegionError error) {
if (deliverMessages()) {
- handler.post(() -> {
- if (observer != null) {
- observer.onError(error);
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (observer != null) {
+ observer.onError(error);
+ }
}
});
}
@@ -272,9 +277,12 @@ public class OfflineRegion {
@Override
public void mapboxTileCountLimitExceeded(final long limit) {
if (deliverMessages()) {
- handler.post(() -> {
- if (observer != null) {
- observer.mapboxTileCountLimitExceeded(limit);
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ if (observer != null) {
+ observer.mapboxTileCountLimitExceeded(limit);
+ }
}
});
}
@@ -313,17 +321,23 @@ public class OfflineRegion {
getOfflineRegionStatus(new OfflineRegionStatusCallback() {
@Override
public void onStatus(final OfflineRegionStatus status) {
- handler.post(() -> {
- callback.onStatus(status);
- FileSource.getInstance(Mapbox.getApplicationContext()).deactivate();
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onStatus(status);
+ FileSource.getInstance(Mapbox.getApplicationContext()).deactivate();
+ }
});
}
@Override
public void onError(final String error) {
- handler.post(() -> {
- callback.onError(error);
- FileSource.getInstance(Mapbox.getApplicationContext()).deactivate();
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onError(error);
+ FileSource.getInstance(Mapbox.getApplicationContext()).deactivate();
+ }
});
}
});
@@ -353,19 +367,25 @@ public class OfflineRegion {
deleteOfflineRegion(new OfflineRegionDeleteCallback() {
@Override
public void onDelete() {
- handler.post((Runnable) () -> {
- callback.onDelete();
- FileSource.getInstance(Mapbox.getApplicationContext()).deactivate();
- OfflineRegion.this.finalize();
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onDelete();
+ FileSource.getInstance(Mapbox.getApplicationContext()).deactivate();
+ OfflineRegion.this.finalize();
+ }
});
}
@Override
public void onError(final String error) {
- handler.post(() -> {
- isDeleted = false;
- FileSource.getInstance(Mapbox.getApplicationContext()).deactivate();
- callback.onError(error);
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ isDeleted = false;
+ FileSource.getInstance(Mapbox.getApplicationContext()).deactivate();
+ callback.onError(error);
+ }
});
}
});
@@ -386,15 +406,23 @@ public class OfflineRegion {
updateOfflineRegionMetadata(bytes, new OfflineRegionUpdateMetadataCallback() {
@Override
public void onUpdate(final byte[] metadata) {
- handler.post(() -> {
- OfflineRegion.this.metadata = metadata;
- callback.onUpdate(metadata);
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ OfflineRegion.this.metadata = metadata;
+ callback.onUpdate(metadata);
+ }
});
}
@Override
public void onError(final String error) {
- handler.post(() -> callback.onError(error));
+ handler.post(new Runnable() {
+ @Override
+ public void run() {
+ callback.onError(error);
+ }
+ });
}
});
}
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 2a32f0bdd6..ea9a066df7 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
@@ -10,12 +10,12 @@ 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.
+ * Both minZoom and maxZoom must be &#x2265; 0, and maxZoom must be &#x2265; minZoom.
* <p>
- * maxZoom may be ∞, in which case for each tile source, the region will include
+ * maxZoom may be &#x221E;, 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.
+ * pixelRatio must be &#x2265; 0 and should typically be 1.0 or 2.0.
*/
public class OfflineTilePyramidRegionDefinition implements OfflineRegionDefinition, Parcelable {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java
index 1c59bb468e..0895096f6e 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/MapSnapshotter.java
@@ -82,7 +82,7 @@ public class MapSnapshotter {
* MapSnapshotter options
*/
public static class Options {
- private int pixelRatio = 1;
+ private float pixelRatio = 1;
private int width;
private int height;
private String styleUrl = Style.MAPBOX_STREETS;
@@ -95,6 +95,9 @@ public class MapSnapshotter {
* @param height the height of the image
*/
public Options(int width, int height) {
+ if (width == 0 || height == 0) {
+ throw new IllegalArgumentException("Unable to create a snapshot with width or height set to 0");
+ }
this.width = width;
this.height = height;
}
@@ -122,7 +125,7 @@ public class MapSnapshotter {
* @param pixelRatio the pixel ratio to use (default: 1)
* @return the mutated {@link Options}
*/
- public Options withPixelRatio(int pixelRatio) {
+ public Options withPixelRatio(float pixelRatio) {
this.pixelRatio = pixelRatio;
return this;
}
@@ -164,7 +167,7 @@ public class MapSnapshotter {
/**
* @return the pixel ratio
*/
- public int getPixelRatio() {
+ public float getPixelRatio() {
return pixelRatio;
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/package-info.java
new file mode 100644
index 0000000000..f1ce247ba8
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/snapshotter/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Contains the Mapbox Maps Android Snapshotter API classes.
+ */
+package com.mapbox.mapboxsdk.snapshotter;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java
index 7b841a2580..bd5b40c6ce 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/Expression.java
@@ -5,16 +5,20 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.Size;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonPrimitive;
import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
+import com.mapbox.mapboxsdk.style.layers.PropertyValue;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
/**
* The value for any layout property, paint property, or filter may be specified as an expression.
* An expression defines a formula for computing the value of the property using the operators described below.
* The set of expression operators provided by Mapbox GL includes:
- * <p>
* <ul>
* <li>Element</li>
* <li>Mathematical operators for performing arithmetic and other operations on numeric values</li>
@@ -23,7 +27,6 @@ import java.util.List;
* <li>Data operators, providing access to the properties of source features</li>
* <li>Camera operators, providing access to the parameters defining the current map view</li>
* </ul>
- * </p>
* <p>
* Expressions are represented as JSON arrays.
* The first element of an expression array is a string naming the expression operator,
@@ -46,10 +49,40 @@ import java.util.List;
* Such composite expressions allows a layer's appearance to be determined by
* a combination of the zoom level and individual feature properties.
* </p>
- *
- * @param <T> the type of the expression
+ * <p>
+ * Example expression:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(
+ * interpolate( linear(), zoom(),
+ * stop(12, step(get("stroke-width"),
+ * color(Color.BLACK),
+ * stop(1f, color(Color.RED)),
+ * stop(2f, color(Color.WHITE)),
+ * stop(3f, color(Color.BLUE))
+ * )),
+ * stop(15, step(get("stroke-width"),
+ * color(Color.BLACK),
+ * stop(1f, color(Color.YELLOW)),
+ * stop(2f, color(Color.LTGRAY)),
+ * stop(3f, color(Color.CYAN))
+ * )),
+ * stop(18, step(get("stroke-width"),
+ * color(Color.BLACK),
+ * stop(1f, color(Color.WHITE)),
+ * stop(2f, color(Color.GRAY)),
+ * stop(3f, color(Color.GREEN))
+ * ))
+ * )
+ * )
+ * )
+ * }
+ * </pre>
*/
-public class Expression<T> {
+public class Expression {
private final String operator;
private final Expression[] arguments;
@@ -68,205 +101,116 @@ public class Expression<T> {
* @param operator the expression operator
* @param arguments expressions input
*/
- @SafeVarargs
public Expression(@NonNull String operator, @Nullable Expression... arguments) {
this.operator = operator;
this.arguments = arguments;
}
/**
- * Converts the expression to Object array representation.
+ * Create a literal number expression.
* <p>
- * The output will later be converted to a JSON Object array.
+ * Example usage:
* </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(literal(10.0f))
+ * );
+ * }
+ * </pre>
*
- * @return the converted object array expression
- */
- @NonNull
- public Object[] toArray() {
- List<Object> array = new ArrayList<>();
- array.add(operator);
- if (arguments != null) {
- for (Expression argument : arguments) {
- if (argument instanceof Expression.ExpressionLiteral) {
- array.add(toValue((ExpressionLiteral) argument));
- } else {
- array.add(argument.toArray());
- }
- }
- }
- return array.toArray();
- }
-
- /**
- * Converts the expression value to an Object.
- *
- * @param expressionValue the expression value to convert
- * @return the converted object expression
+ * @param number the number
+ * @return the expression
*/
- private Object toValue(ExpressionLiteral expressionValue) {
- Object value = expressionValue.toValue();
- if (value instanceof Expression.Color) {
- return ((Expression.Color) value).convertColor();
- } else if (value instanceof Expression.ExpressionLiteral) {
- return toValue((ExpressionLiteral) value);
- } else if (value instanceof Expression) {
- return ((Expression) value).toArray();
- }
- return value;
+ public static Expression literal(@NonNull Number number) {
+ return new ExpressionLiteral(number);
}
/**
- * ExpressionLiteral wraps an object to be used as a literal in an expression.
+ * Create a literal string expression.
* <p>
- * ExpressionLiteral is created with {@link #literal(Number)}, {@link #literal(boolean)},
- * {@link #literal(String)} and {@link #literal(Object)}.
+ * Example usage:
* </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(literal("Text"))
+ * );
+ * }
+ * </pre>
*
- * @param <T>
- */
- private static class ExpressionLiteral<T> extends Expression<T> {
-
- protected T object;
-
- /**
- * Create an ExpressionValue wrapper.
- *
- * @param object the object to be wrapped
- */
- ExpressionLiteral(@NonNull T object) {
- this.object = object;
- }
-
- /**
- * Get the wrapped object.
- *
- * @return the wrapped object
- */
- Object toValue() {
- return object;
- }
- }
-
- //
- // Types
- //
-
- /**
- * Expression interpolator type.
- * <p>
- * Is used for first parameter of {@link #interpolate(Expression, Expression, Stop...)}.
- * </p>
- */
- public static class Interpolator {
- }
-
- /**
- * Expression color type.
+ * @param string the string
+ * @return the expression
*/
- public static class Color {
-
- private int color;
-
- /**
- * Creates a color color type from a color int.
- *
- * @param color the int color
- */
- public Color(@ColorInt int color) {
- this.color = color;
- }
-
- /**
- * Converts the int color to rgba(d, d, d, d) string representation
- *
- * @return
- */
- public String convertColor() {
- return PropertyFactory.colorToRgbaString(color);
- }
+ public static Expression literal(@NonNull String string) {
+ return new ExpressionLiteral(string);
}
/**
- * Expression array type.
- */
- public static class Array {
- }
-
- /**
- * Expression stop type.
+ * Create a literal boolean expression.
* <p>
- * Can be used for {@link #stop(Object, Object)} as part of varargs parameter in
- * {@link #step(Number, Expression, Stop...)} or {@link #interpolate(Expression, Expression, Stop...)}.
+ * Example usage:
* </p>
- */
- public static class Stop {
-
- private Object value;
- private Object output;
-
- public Stop(Object value, Object output) {
- this.value = value;
- this.output = output;
- }
- }
-
- //
- // Literals
- //
-
- /**
- * Create a literal number expression.
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillAntialias(literal(true))
+ * );
+ * }
+ * </pre>
*
- * @param number the number
- * @return the expression
- */
- public static Expression<Number> literal(@NonNull Number number) {
- return new ExpressionLiteral<>(number);
- }
-
- /**
- * Create a literal string expression.
- *
- * @param string the string
+ * @param bool the boolean
* @return the expression
*/
- public static Expression<String> literal(@NonNull String string) {
- return new ExpressionLiteral<>(string);
+ public static Expression literal(boolean bool) {
+ return new ExpressionLiteral(bool);
}
/**
- * Create a literal boolean expression.
+ * Create a literal object expression.
*
- * @param bool the boolean
+ * @param object the object
* @return the expression
*/
- public static Expression<Boolean> literal(boolean bool) {
- return new ExpressionLiteral<>(bool);
+ public static Expression literal(@NonNull Object object) {
+ if (object.getClass().isArray()) {
+ return literal(ExpressionArray.toObjectArray(object));
+ }
+ return new ExpressionLiteral(object);
}
/**
- * Create a literal object expression
+ * Create a literal array expression
*
- * @param object the object
+ * @param array the array
* @return the expression
*/
- public static Expression<Object> literal(@NonNull Object object) {
- return new ExpressionLiteral<>(object);
+ public static Expression literal(@NonNull Object[] array) {
+ return new ExpressionArray(array);
}
- //
- // Color
- //
-
/**
* Expression literal utility method to convert a color int to an color expression
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(color(Color.GREEN))
+ * );
+ * }
+ * </pre>
*
* @param color the int color
* @return the color expression
*/
- public static Expression<Color> color(@ColorInt int color) {
- return new ExpressionLiteral<>(new Color(color));
+ public static Expression color(@ColorInt int color) {
+ return toColor(literal(PropertyFactory.colorToRgbaString(color)));
}
/**
@@ -275,15 +219,32 @@ public class Expression<T> {
* <p>
* If any component is out of range, the expression is an error.
* </p>
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(
+ * rgb(
+ * literal(255.0f),
+ * literal(255.0f),
+ * literal(255.0f)
+ * )
+ * )
+ * );
+ * }
+ * </pre>
*
* @param red red color expression
* @param green green color expression
* @param blue blue color expression
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-rgb">Style specification</a>
*/
- public static Expression<Color> rgb(@NonNull Expression<Number> red, @NonNull Expression<Number> green,
- @NonNull Expression<Number> blue) {
- return new Expression<>("rgb", red, green, blue);
+ public static Expression rgb(@NonNull Expression red, @NonNull Expression green, @NonNull Expression blue) {
+ return new Expression("rgb", red, green, blue);
}
/**
@@ -292,13 +253,27 @@ public class Expression<T> {
* <p>
* If any component is out of range, the expression is an error.
* </p>
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(
+ * rgb(255.0f, 255.0f, 255.0f)
+ * )
+ * );
+ * }
+ * </pre>
*
* @param red red color value
* @param green green color value
* @param blue blue color value
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-rgb">Style specification</a>
*/
- public static Expression<Color> rgb(@NonNull Number red, @NonNull Number green, @NonNull Number blue) {
+ public static Expression rgb(@NonNull Number red, @NonNull Number green, @NonNull Number blue) {
return rgb(literal(red), literal(green), literal(blue));
}
@@ -308,16 +283,35 @@ public class Expression<T> {
* <p>
* If any component is out of range, the expression is an error.
* </p>
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(
+ * rgba(
+ * literal(255.0f),
+ * literal(255.0f),
+ * literal(255.0f),
+ * literal(1.0f)
+ * )
+ * )
+ * );
+ * }
+ * </pre>
*
* @param red red color value
* @param green green color value
* @param blue blue color value
* @param alpha alpha color value
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-rgba">Style specification</a>
*/
- public static Expression<Color> rgba(@NonNull Expression<Number> red, @NonNull Expression<Number> green,
- @NonNull Expression<Number> blue, @NonNull Expression<Number> alpha) {
- return new Expression<>("rgba", red, green, blue, alpha);
+ public static Expression rgba(@NonNull Expression red, @NonNull Expression green,
+ @NonNull Expression blue, @NonNull Expression alpha) {
+ return new Expression("rgba", red, green, blue, alpha);
}
/**
@@ -326,14 +320,28 @@ public class Expression<T> {
* <p>
* If any component is out of range, the expression is an error.
* </p>
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(
+ * rgb(255.0f, 255.0f, 255.0f, 1.0f)
+ * )
+ * );
+ * }
+ * </pre>
*
* @param red red color value
* @param green green color value
* @param blue blue color value
* @param alpha alpha color value
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-rgba">Style specification</a>
*/
- public static Expression<Color> rgba(@NonNull Number red, @NonNull Number green, @NonNull Number blue, @NonNull Number alpha) {
+ public static Expression rgba(@NonNull Number red, @NonNull Number green, @NonNull Number blue, @NonNull Number alpha) {
return rgba(literal(red), literal(green), literal(blue), literal(alpha));
}
@@ -342,239 +350,476 @@ public class Expression<T> {
*
* @param expression an expression to convert to a color
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-to-rgba">Style specification</a>
*/
- public static Expression<Array> toRgba(@NonNull Expression<Color> expression) {
- return new Expression<>("to-rgba", expression);
+ public static Expression toRgba(@NonNull Expression expression) {
+ return new Expression("to-rgba", expression);
}
- //
- // Decision
- //
-
/**
* Returns true if the input values are equal, false otherwise.
* The inputs must be numbers, strings, or booleans, and both of the same type.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * eq(get("keyToValue"), get("keyToOtherValue"))
+ * );
+ * }
+ * </pre>
*
* @param compareOne the first expression
* @param compareTwo the second expression
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-==">Style specification</a>
*/
- public static Expression<Boolean> eq(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
- return new Expression<>("==", compareOne, compareTwo);
+ public static Expression eq(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression("==", compareOne, compareTwo);
}
/**
* Returns true if the input values are equal, false otherwise.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * eq(get("keyToValue"), true)
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first boolean
+ * @param compareOne the first expression
* @param compareTwo the second boolean
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-==">Style specification</a>
*/
- public static Expression<Boolean> eq(boolean compareOne, boolean compareTwo) {
- return eq(literal(compareOne), literal(compareTwo));
+ public static Expression eq(Expression compareOne, boolean compareTwo) {
+ return eq(compareOne, literal(compareTwo));
}
/**
* Returns true if the input values are equal, false otherwise.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * eq(get("keyToValue"), "value")
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first number
+ * @param compareOne the first expression
* @param compareTwo the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-==">Style specification</a>
*/
- public static Expression<Boolean> eq(@NonNull String compareOne, @NonNull String compareTwo) {
+ public static Expression eq(@NonNull Expression compareOne, @NonNull String compareTwo) {
return eq(literal(compareOne), literal(compareTwo));
}
/**
* Returns true if the input values are equal, false otherwise.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * eq(get("keyToValue"), 2.0f)
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first number
+ * @param compareOne the first expression
* @param compareTwo the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-==">Style specification</a>
*/
- public static Expression<Boolean> eq(@NonNull Number compareOne, @NonNull Number compareTwo) {
+ public static Expression eq(@NonNull Expression compareOne, @NonNull Number compareTwo) {
return eq(literal(compareOne), literal(compareTwo));
}
/**
* Returns true if the input values are not equal, false otherwise.
* The inputs must be numbers, strings, or booleans, and both of the same type.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * neq(get("keyToValue"), get("keyToOtherValue"))
+ * );
+ * }
+ * </pre>
*
* @param compareOne the first expression
* @param compareTwo the second expression
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-!=">Style specification</a>
*/
- public static Expression<Boolean> neq(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
- return new Expression<>("!=", compareOne, compareTwo);
+ public static Expression neq(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression("!=", compareOne, compareTwo);
}
/**
* Returns true if the input values are equal, false otherwise.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * neq(get("keyToValue"), true)
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first boolean
+ * @param compareOne the first expression
* @param compareTwo the second boolean
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-!=">Style specification</a>
*/
- public static Expression<Boolean> neq(boolean compareOne, boolean compareTwo) {
- return new Expression<>("!=", literal(compareOne), literal(compareTwo));
+ public static Expression neq(Expression compareOne, boolean compareTwo) {
+ return new Expression("!=", literal(compareOne), literal(compareTwo));
}
/**
* Returns `true` if the input values are not equal, `false` otherwise.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * neq(get("keyToValue"), "value"))
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first string
+ * @param compareOne the first expression
* @param compareTwo the second string
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-!=">Style specification</a>
*/
- public static Expression<Boolean> neq(@NonNull String compareOne, @NonNull String compareTwo) {
- return new Expression<>("!=", literal(compareOne), literal(compareTwo));
+ public static Expression neq(@NonNull Expression compareOne, @NonNull String compareTwo) {
+ return new Expression("!=", literal(compareOne), literal(compareTwo));
}
/**
* Returns `true` if the input values are not equal, `false` otherwise.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * neq(get("keyToValue"), 2.0f))
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first number
+ * @param compareOne the first expression
* @param compareTwo the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-!=">Style specification</a>
*/
- public static Expression<Boolean> neq(@NonNull Number compareOne, @NonNull Number compareTwo) {
- return new Expression<>("!=", literal(compareOne), literal(compareTwo));
+ public static Expression neq(@NonNull Expression compareOne, @NonNull Number compareTwo) {
+ return new Expression("!=", literal(compareOne), literal(compareTwo));
}
/**
* Returns true if the first input is strictly greater than the second, false otherwise.
* The inputs must be numbers or strings, and both of the same type.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * gt(get("keyToValue"), get("keyToOtherValue"))
+ * );
+ * }
+ * </pre>
*
* @param compareOne the first expression
* @param compareTwo the second expression
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3E">Style specification</a>
*/
- public static Expression<Boolean> gt(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
- return new Expression<>(">", compareOne, compareTwo);
+ public static Expression gt(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression(">", compareOne, compareTwo);
}
/**
* Returns true if the first input is strictly greater than the second, false otherwise.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * gt(get("keyToValue"), 2.0f)
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first number
+ * @param compareOne the first expression
* @param compareTwo the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3E">Style specification</a>
*/
- public static Expression<Boolean> gt(@NonNull Number compareOne, @NonNull Number compareTwo) {
- return new Expression<>(">", literal(compareOne), literal(compareTwo));
+ public static Expression gt(@NonNull Expression compareOne, @NonNull Number compareTwo) {
+ return new Expression(">", literal(compareOne), literal(compareTwo));
}
/**
* Returns true if the first input is strictly greater than the second, false otherwise.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * gt(get("keyToValue"), "value")
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first string
+ * @param compareOne the first expression
* @param compareTwo the second string
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3E">Style specification</a>
*/
- public static Expression<Boolean> gt(@NonNull String compareOne, @NonNull String compareTwo) {
- return new Expression<>(">", literal(compareOne), literal(compareTwo));
+ public static Expression gt(@NonNull Expression compareOne, @NonNull String compareTwo) {
+ return new Expression(">", literal(compareOne), literal(compareTwo));
}
/**
* Returns true if the first input is strictly less than the second, false otherwise.
* The inputs must be numbers or strings, and both of the same type.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * lt(get("keyToValue"), get("keyToOtherValue"))
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first number
+ * @param compareOne the first expression
* @param compareTwo the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3C">Style specification</a>
*/
- public static Expression<Boolean> lt(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
- return new Expression<>("<", compareOne, compareTwo);
+ public static Expression lt(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression("<", compareOne, compareTwo);
}
/**
* Returns true if the first input is strictly less than the second, false otherwise.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * lt(get("keyToValue"), 2.0f)
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first number
+ * @param compareOne the first expression
* @param compareTwo the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3C">Style specification</a>
*/
- public static Expression<Boolean> lt(@NonNull Number compareOne, @NonNull Number compareTwo) {
- return new Expression<>("<", literal(compareOne), literal(compareTwo));
+ public static Expression lt(@NonNull Expression compareOne, @NonNull Number compareTwo) {
+ return new Expression("<", literal(compareOne), literal(compareTwo));
}
/**
* Returns true if the first input is strictly less than the second, false otherwise.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * lt(get("keyToValue"), "value"))
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first string
+ * @param compareOne the first expression
* @param compareTwo the second string
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3C">Style specification</a>
*/
- public static Expression<Boolean> lt(@NonNull String compareOne, @NonNull String compareTwo) {
- return new Expression<>("<", literal(compareOne), literal(compareTwo));
+ public static Expression lt(@NonNull Expression compareOne, @NonNull String compareTwo) {
+ return new Expression("<", literal(compareOne), literal(compareTwo));
}
/**
* Returns true if the first input is greater than or equal to the second, false otherwise.
* The inputs must be numbers or strings, and both of the same type.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * gte(get("keyToValue"), get("keyToOtherValue"))
+ * );
+ * }
+ * </pre>
*
* @param compareOne the first expression
* @param compareTwo the second expression
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3E%3D">Style specification</a>
*/
- public static Expression<Boolean> gte(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
- return new Expression<>(">=", compareOne, compareTwo);
+ public static Expression gte(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression(">=", compareOne, compareTwo);
}
/**
* Returns true if the first input is greater than or equal to the second, false otherwise.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * gte(get("keyToValue"), 2.0f)
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first number
+ * @param compareOne the first expression
* @param compareTwo the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3E%3D">Style specification</a>
*/
- public static Expression<Boolean> gte(@NonNull Number compareOne, @NonNull Number compareTwo) {
- return new Expression<>(">=", literal(compareOne), literal(compareTwo));
+ public static Expression gte(@NonNull Expression compareOne, @NonNull Number compareTwo) {
+ return new Expression(">=", literal(compareOne), literal(compareTwo));
}
/**
* Returns true if the first input is greater than or equal to the second, false otherwise.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * neq(get("keyToValue"), "value")
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first string
+ * @param compareOne the first expression
* @param compareTwo the second string
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3E%3D">Style specification</a>
*/
- public static Expression<Boolean> gte(@NonNull String compareOne, @NonNull String compareTwo) {
- return new Expression<>(">=", literal(compareOne), literal(compareTwo));
+ public static Expression gte(@NonNull Expression compareOne, @NonNull String compareTwo) {
+ return new Expression(">=", literal(compareOne), literal(compareTwo));
}
/**
* Returns true if the first input is less than or equal to the second, false otherwise.
* The inputs must be numbers or strings, and both of the same type.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * lte(get("keyToValue"), get("keyToOtherValue"))
+ * );
+ * }
+ * </pre>
*
* @param compareOne the first expression
* @param compareTwo the second expression
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3C%3D">Style specification</a>
*/
- public static Expression<Boolean> lte(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
- return new Expression<>("<=", compareOne, compareTwo);
+ public static Expression lte(@NonNull Expression compareOne, @NonNull Expression compareTwo) {
+ return new Expression("<=", compareOne, compareTwo);
}
/**
* Returns true if the first input is less than or equal to the second, false otherwise.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * lte(get("keyToValue"), 2.0f)
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first number
+ * @param compareOne the first expression
* @param compareTwo the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3C%3D">Style specification</a>
*/
- public static Expression<Boolean> lte(@NonNull Number compareOne, @NonNull Number compareTwo) {
- return new Expression<>("<=", literal(compareOne), literal(compareTwo));
+ public static Expression lte(@NonNull Expression compareOne, @NonNull Number compareTwo) {
+ return new Expression("<=", literal(compareOne), literal(compareTwo));
}
/**
* Returns true if the first input is less than or equal to the second, false otherwise.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * lte(get("keyToValue"), "value")
+ * );
+ * }
+ * </pre>
*
- * @param compareOne the first string
+ * @param compareOne the first expression
* @param compareTwo the second string
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%3C%3D">Style specification</a>
*/
- public static Expression<Boolean> lte(@NonNull String compareOne, @NonNull String compareTwo) {
- return new Expression<>("<=", literal(compareOne), literal(compareTwo));
+ public static Expression lte(@NonNull Expression compareOne, @NonNull String compareTwo) {
+ return new Expression("<=", literal(compareOne), literal(compareTwo));
}
/**
@@ -584,13 +829,24 @@ public class Expression<T> {
* once an input expression evaluates to `false`,
* the result is `false` and no further input expressions are evaluated.
* </p>
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * all(get("keyToValue"), get("keyToOtherValue"))
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-all">Style specification</a>
*/
- @SafeVarargs
- public static Expression<Boolean> all(@NonNull Expression<Boolean>... input) {
- return new Expression<>("all", input);
+ public static Expression all(@NonNull Expression... input) {
+ return new Expression("all", input);
}
/**
@@ -600,42 +856,98 @@ public class Expression<T> {
* once an input expression evaluates to `true`,
* the result is `true` and no further input expressions are evaluated.
* </p>
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * any(get("keyToValue"), get("keyToOtherValue"))
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-any">Style specification</a>
*/
- @SafeVarargs
- public static Expression<Boolean> any(@NonNull Expression<Boolean>... input) {
- return new Expression<>("any", input);
+ public static Expression any(@NonNull Expression... input) {
+ return new Expression("any", input);
}
/**
* Logical negation. Returns `true` if the input is `false`, and `false` if the input is `true`.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * not(get("keyToValue"))
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-!">Style specification</a>
*/
- public static Expression<Boolean> not(@NonNull Expression<Boolean> input) {
- return new Expression<>("!", input);
+ public static Expression not(@NonNull Expression input) {
+ return new Expression("!", input);
}
/**
* Logical negation. Returns `true` if the input is `false`, and `false` if the input is `true`.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * not(false)
+ * );
+ * }
+ * </pre>
*
* @param input boolean input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-!">Style specification</a>
*/
- public static Expression<Boolean> not(boolean input) {
+ public static Expression not(boolean input) {
return not(literal(input));
}
/**
* Selects the first output whose corresponding test condition evaluates to true.
+ * <p>
+ * For each case a condition and an output should be provided.
+ * The last parameter should provide the default output.
+ * </p>
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * iconSize(
+ * switchCase(
+ * get(KEY_TO_BOOLEAN), literal(3.0f),
+ * get(KEY_TO_OTHER_BOOLEAN), literal(5.0f)
+ * literal(1.0f) // default value
+ * )
+ * )
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-case">Style specification</a>
*/
- @SafeVarargs
public static Expression switchCase(@NonNull @Size(min = 1) Expression... input) {
return new Expression("case", input);
}
@@ -644,9 +956,29 @@ public class Expression<T> {
* Selects the output whose label value matches the input value, or the fallback value if no match is found.
* The `input` can be any string or number expression.
* Each label can either be a single literal value or an array of values.
+ * If types of the input and keys don't match, or the input value doesn't exist,
+ * the expresion will fail without falling back to the default value.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textColor(
+ * match(get("keyToValue"),
+ * literal(1), rgba(255, 0, 0, 1.0f),
+ * literal(2), rgba(0, 0, 255.0f, 1.0f),
+ * rgba(0.0f, 255.0f, 0.0f, 1.0f)
+ * );
+ * )
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-match">Style specification</a>
*/
public static Expression match(@NonNull @Size(min = 2) Expression... input) {
return new Expression("match", input);
@@ -656,91 +988,172 @@ public class Expression<T> {
* Selects the output whose label value matches the input value, or the fallback value if no match is found.
* The `input` can be any string or number expression.
* Each label can either be a single literal value or an array of values.
+ * If types of the input and keys don't match, or the input value doesn't exist,
+ * the expresion will fail without falling back to the default value.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textColor(
+ * match(get("keyToValue"),
+ * literal(1), rgba(255, 0, 0, 1.0f),
+ * literal(2), rgba(0, 0, 255.0f, 1.0f),
+ * rgba(0.0f, 255.0f, 0.0f, 1.0f)
+ * );
+ * )
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-match">Style specification</a>
*/
- public static Expression match(@NonNull Expression input, @NonNull Stop... stops) {
- Expression[] expressions = new Expression[stops.length * 2];
+ public static Expression match(@NonNull Expression input, @NonNull Expression defaultOutput, @NonNull Stop... stops) {
+ Expression[] expressionStops = new Expression[stops.length * 2];
for (int i = 0; i < stops.length; i++) {
- expressions[i * 2] = literal(stops[i].value);
- expressions[i * 2 + 1] = literal(stops[i].output);
+ expressionStops[i * 2] = literal(stops[i].value);
+ expressionStops[i * 2 + 1] = literal(stops[i].output);
}
- return match(join(new Expression[] {input}, expressions));
+ return match(join(join(new Expression[] {input}, expressionStops), new Expression[] {defaultOutput}));
}
/**
* Evaluates each expression in turn until the first non-null value is obtained, and returns that value.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textColor(
+ * coalesce(
+ * get("keyToNullValue"),
+ * get("keyToNonNullValue")
+ * );
+ * )
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-coalesce">Style specification</a>
*/
public static Expression coalesce(@NonNull Expression... input) {
return new Expression("coalesce", input);
}
- //
- // FeatureData
- //
-
/**
* Gets the feature properties object.
* <p>
* Note that in some cases, it may be more efficient to use {@link #get(Expression)}} instead.
* </p>
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(get("key-to-value", properties())))
+ * );
+ * }
+ * </pre>
*
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-properties">Style specification</a>
*/
- public static Expression<Object> properties() {
- return new Expression<>("properties");
+ public static Expression properties() {
+ return new Expression("properties");
}
/**
* Gets the feature's geometry type: Point, MultiPoint, LineString, MultiLineString, Polygon, MultiPolygon.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(concat(get("key-to-value"), literal(" "), geometryType())
+ * );
+ * }
+ * </pre>
*
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-geometry-types">Style specification</a>
*/
- public static Expression<String> geometryType() {
- return new Expression<>("geometry-type");
+ public static Expression geometryType() {
+ return new Expression("geometry-type");
}
/**
* Gets the feature's id, if it has one.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(id())
+ * );
+ * }
+ * </pre>
*
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-id">Style specification</a>
*/
- public static Expression<Number> id() {
- return new Expression<>("id");
+ public static Expression id() {
+ return new Expression("id");
}
- //
- // Heatmap
- //
-
/**
* Gets the kernel density estimation of a pixel in a heatmap layer,
* which is a relative measure of how many data points are crowded around a particular pixel.
* Can only be used in the `heatmap-color` property.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * HeatmapLayer layer = new HeatmapLayer("layer-id", "source-id");
+ * layer.setProperties(
+ * heatmapColor(interpolate(linear(), heatmapDensity(),
+ * literal(0), rgba(33, 102, 172, 0),
+ * literal(0.2), rgb(103, 169, 207),
+ * literal(0.4), rgb(209, 229, 240),
+ * literal(0.6), rgb(253, 219, 199),
+ * literal(0.8), rgb(239, 138, 98),
+ * literal(1), rgb(178, 24, 43)
+ * )
+ * )
+ * }
+ * </pre>
*
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-heatmap-density">Style specification</a>
*/
- public static Expression<Number> heatmapDensity() {
- return new Expression<>("heatmap-density");
+ public static Expression heatmapDensity() {
+ return new Expression("heatmap-density");
}
- //
- // Lookup
- //
-
/**
* Retrieves an item from an array.
*
* @param number the index expression
* @param expression the array expression
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-at">Style specification</a>
*/
- public static Expression<Object> at(@NonNull Expression<Number> number, @NonNull Expression expression) {
- return new Expression<>("at", number, expression);
+ public static Expression at(@NonNull Expression number, @NonNull Expression expression) {
+ return new Expression("at", number, expression);
}
/**
@@ -749,8 +1162,9 @@ public class Expression<T> {
* @param number the index expression
* @param expression the array expression
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-at">Style specification</a>
*/
- public static Expression<Object> at(@NonNull Number number, @NonNull Expression expression) {
+ public static Expression at(@NonNull Number number, @NonNull Expression expression) {
return at(literal(number), expression);
}
@@ -758,21 +1172,45 @@ public class Expression<T> {
* Retrieves a property value from the current feature's properties,
* or from another object if a second argument is provided.
* Returns null if the requested property is missing.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(get("key-to-feature"))
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-get">Style specification</a>
*/
- public static Expression get(@NonNull Expression<String> input) {
- return new Expression<>("get", input);
+ public static Expression get(@NonNull Expression input) {
+ return new Expression("get", input);
}
/**
* Retrieves a property value from the current feature's properties,
* or from another object if a second argument is provided.
* Returns null if the requested property is missing.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(get("key-to-feature"))
+ * );
+ * }
+ * </pre>
*
* @param input string input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-get">Style specification</a>
*/
public static Expression get(@NonNull String input) {
return get(literal(input));
@@ -781,66 +1219,138 @@ public class Expression<T> {
/**
* Retrieves a property value from another object.
* Returns null if the requested property is missing.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(get("key-to-property", get("key-to-object")))
+ * );
+ * }
+ * </pre>
*
* @param key a property value key
* @param object an expression object
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-get">Style specification</a>
*/
- public static Expression<Object> get(@NonNull Expression<String> key, @NonNull Expression<Object> object) {
- return new Expression<>("get", key, object);
+ public static Expression get(@NonNull Expression key, @NonNull Expression object) {
+ return new Expression("get", key, object);
}
/**
* Retrieves a property value from another object.
* Returns null if the requested property is missing.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(get("key-to-property", get("key-to-object")))
+ * );
+ * }
+ * </pre>
*
* @param key a property value key
* @param object an expression object
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-get">Style specification</a>
*/
- public static Expression<Object> get(@NonNull String key, @NonNull Expression<Object> object) {
+ public static Expression get(@NonNull String key, @NonNull Expression object) {
return get(literal(key), object);
}
/**
* Tests for the presence of an property value in the current feature's properties.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * has(get("keyToValue"))
+ * );
+ * }
+ * </pre>
*
* @param key the expression property value key
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-has">Style specification</a>
*/
- public static Expression<Boolean> has(@NonNull Expression<String> key) {
- return new Expression<>("has", key);
+ public static Expression has(@NonNull Expression key) {
+ return new Expression("has", key);
}
/**
* Tests for the presence of an property value in the current feature's properties.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * has("keyToValue")
+ * );
+ * }
+ * </pre>
*
* @param key the property value key
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-has">Style specification</a>
*/
- public static Expression<Boolean> has(@NonNull String key) {
+ public static Expression has(@NonNull String key) {
return has(literal(key));
}
/**
* Tests for the presence of an property value from another object.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * has(get("keyToValue"), get("keyToObject"))
+ * );
+ * }
+ * </pre>
*
* @param key the expression property value key
* @param object an expression object
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-has">Style specification</a>
*/
- public static Expression<Boolean> has(@NonNull Expression<String> key, @NonNull Expression<Object> object) {
- return new Expression<>("has", key, object);
+ public static Expression has(@NonNull Expression key, @NonNull Expression object) {
+ return new Expression("has", key, object);
}
/**
* Tests for the presence of an property value from another object.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setFilter(
+ * has("keyToValue", get("keyToObject))
+ * );
+ * }
+ * </pre>
*
* @param key the property value key
* @param object an expression object
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-has">Style specification</a>
*/
- public static Expression<Boolean> has(@NonNull String key, @NonNull Expression<Object> object) {
+ public static Expression has(@NonNull String key, @NonNull Expression object) {
return has(literal(key), object);
}
@@ -849,9 +1359,10 @@ public class Expression<T> {
*
* @param expression an expression object or expression string
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-lenght">Style specification</a>
*/
- public static Expression<Number> length(@NonNull Expression<?> expression) {
- return new Expression<>("length", expression);
+ public static Expression length(@NonNull Expression expression) {
+ return new Expression("length", expression);
}
/**
@@ -859,62 +1370,117 @@ public class Expression<T> {
*
* @param input a string
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-lenght">Style specification</a>
*/
- public static Expression<Number> length(@NonNull String input) {
+ public static Expression length(@NonNull String input) {
return length(literal(input));
}
- //
- // Math
- //
-
/**
* Returns mathematical constant ln(2).
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(product(literal(10.0f), ln2())))
+ * );
+ * }
+ * </pre>
*
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-ln2">Style specification</a>
*/
- public static Expression<Number> ln2() {
- return new Expression<>("ln2");
+ public static Expression ln2() {
+ return new Expression("ln2");
}
/**
* Returns the mathematical constant pi.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(product(literal(10.0f), pi())))
+ * );
+ * }
+ * </pre>
*
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-pi">Style specification</a>
*/
- public static Expression<Number> pi() {
- return new Expression<>("pi");
+ public static Expression pi() {
+ return new Expression("pi");
}
/**
* Returns the mathematical constant e.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(product(literal(10.0f), e())))
+ * );
+ * }
+ * </pre>
*
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-e">Style specification</a>
*/
- public static Expression<Number> e() {
- return new Expression<>("e");
+ public static Expression e() {
+ return new Expression("e");
}
/**
* Returns the sum of the inputs.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(sum(literal(10.0f), ln2(), pi())))
+ * );
+ * }
+ * </pre>
*
* @param numbers the numbers to calculate the sum for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-+">Style specification</a>
*/
- @SafeVarargs
- public static Expression<Number> sum(@Size(min = 2) Expression<Number>... numbers) {
- return new Expression<>("+", numbers);
+ public static Expression sum(@Size(min = 2) Expression... numbers) {
+ return new Expression("+", numbers);
}
/**
* Returns the sum of the inputs.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(sum(10.0f, 5.0f, 3.0f)))
+ * );
+ * }
+ * </pre>
*
* @param numbers the numbers to calculate the sum for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-+">Style specification</a>
*/
- @SuppressWarnings("unchecked")
- public static Expression<Number> sum(@Size(min = 2) Number... numbers) {
- Expression<Number>[] numberExpression = (Expression<Number>[]) new Expression<?>[numbers.length];
+ public static Expression sum(@Size(min = 2) Number... numbers) {
+ Expression[] numberExpression = new Expression[numbers.length];
for (int i = 0; i < numbers.length; i++) {
numberExpression[i] = literal(numbers[i]);
}
@@ -923,24 +1489,46 @@ public class Expression<T> {
/**
* Returns the product of the inputs.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(product(literal(10.0f), ln2())))
+ * );
+ * }
+ * </pre>
*
* @param numbers the numbers to calculate the product for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-*">Style specification</a>
*/
- @SafeVarargs
- public static Expression<Number> product(@Size(min = 2) Expression<Number>... numbers) {
- return new Expression<>("*", numbers);
+ public static Expression product(@Size(min = 2) Expression... numbers) {
+ return new Expression("*", numbers);
}
/**
* Returns the product of the inputs.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(product(10.0f, 2.0f)))
+ * );
+ * }
+ * </pre>
*
* @param numbers the numbers to calculate the product for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-*">Style specification</a>
*/
- @SuppressWarnings("unchecked")
- public static Expression<Number> product(@Size(min = 2) Number... numbers) {
- Expression<Number>[] numberExpression = (Expression<Number>[]) new Expression<?>[numbers.length];
+ public static Expression product(@Size(min = 2) Number... numbers) {
+ Expression[] numberExpression = new Expression[numbers.length];
for (int i = 0; i < numbers.length; i++) {
numberExpression[i] = literal(numbers[i]);
}
@@ -949,334 +1537,714 @@ public class Expression<T> {
/**
* Returns the result of subtracting a number from 0.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(subtract(pi()))
+ * );
+ * }
+ * </pre>
*
* @param number the number subtract from 0
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions--">Style specification</a>
*/
- public static Expression<Number> subtract(@NonNull Expression<Number> number) {
- return new Expression<>("-", number);
+ public static Expression subtract(@NonNull Expression number) {
+ return new Expression("-", number);
}
/**
* Returns the result of subtracting a number from 0.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(subtract(10.0f))
+ * );
+ * }
+ * </pre>
*
* @param number the number subtract from 0
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions--">Style specification</a>
*/
- public static Expression<Number> subtract(@NonNull Number number) {
+ public static Expression subtract(@NonNull Number number) {
return subtract(literal(number));
}
/**
* Returns the result of subtracting the second input from the first.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(subtract(literal(10.0f), pi())))
+ * );
+ * }
+ * </pre>
*
* @param first the first number
* @param second the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions--">Style specification</a>
*/
- public static Expression<Number> subtract(@NonNull Expression<Number> first, @NonNull Expression<Number> second) {
- return new Expression<>("-", first, second);
+ public static Expression subtract(@NonNull Expression first, @NonNull Expression second) {
+ return new Expression("-", first, second);
}
/**
* Returns the result of subtracting the second input from the first.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(subtract(10.0f, 20.0f)))
+ * );
+ * }
+ * </pre>
*
* @param first the first number
* @param second the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions--">Style specification</a>
*/
- public static Expression<Number> subtract(@NonNull Number first, @NonNull Number second) {
+ public static Expression subtract(@NonNull Number first, @NonNull Number second) {
return subtract(literal(first), literal(second));
}
/**
* Returns the result of floating point division of the first input by the second.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(division(literal(10.0f), pi())))
+ * );
+ * }
+ * </pre>
*
* @param first the first number
* @param second the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-/">Style specification</a>
*/
- @SuppressWarnings("unchecked")
- public static Expression<Number> division(@NonNull Expression<Number> first, @NonNull Expression<Number> second) {
- return new Expression<>("/", first, second);
+ public static Expression division(@NonNull Expression first, @NonNull Expression second) {
+ return new Expression("/", first, second);
}
/**
* Returns the result of floating point division of the first input by the second.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(division(10.0f, 20.0f)))
+ * );
+ * }
+ * </pre>
*
* @param first the first number
* @param second the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-/">Style specification</a>
*/
- @SuppressWarnings("unchecked")
- public static Expression<Number> division(@NonNull Number first, @NonNull Number second) {
+ public static Expression division(@NonNull Number first, @NonNull Number second) {
return division(literal(first), literal(second));
}
/**
* Returns the remainder after integer division of the first input by the second.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(mod(literal(10.0f), pi()))
+ * );
+ * }
+ * </pre>
*
* @param first the first number
* @param second the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%25">Style specification</a>
*/
- public static Expression<Number> mod(@NonNull Expression<Number> first, @NonNull Expression<Number> second) {
- return new Expression<>("%", first, second);
+ public static Expression mod(@NonNull Expression first, @NonNull Expression second) {
+ return new Expression("%", first, second);
}
/**
* Returns the remainder after integer division of the first input by the second.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(mod(10.0f, 10.0f))
+ * );
+ * }
+ * </pre>
*
* @param first the first number
* @param second the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%25">Style specification</a>
*/
- public static Expression<Number> mod(@NonNull Number first, @NonNull Number second) {
+ public static Expression mod(@NonNull Number first, @NonNull Number second) {
return mod(literal(first), literal(second));
}
/**
* Returns the result of raising the first input to the power specified by the second.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(pow(pi(), literal(2.0f))
+ * );
+ * }
+ * </pre>
*
* @param first the first number
* @param second the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%5E">Style specification</a>
*/
- public static Expression<Number> pow(@NonNull Expression<Number> first, @NonNull Expression<Number> second) {
- return new Expression<>("^", first, second);
+ public static Expression pow(@NonNull Expression first, @NonNull Expression second) {
+ return new Expression("^", first, second);
}
/**
* Returns the result of raising the first input to the power specified by the second.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(pow(5.0f, 2.0f))
+ * );
+ * }
+ * </pre>
*
* @param first the first number
* @param second the second number
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-%5E">Style specification</a>
*/
- public static Expression<Number> pow(@NonNull Number first, @NonNull Number second) {
+ public static Expression pow(@NonNull Number first, @NonNull Number second) {
return pow(literal(first), literal(second));
}
/**
* Returns the square root of the input
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(sqrt(pi()))
+ * );
+ * }
+ * </pre>
*
* @param number the number to take the square root from
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-sqrt">Style specification</a>
*/
- public static Expression<Number> sqrt(@NonNull Expression<Number> number) {
- return new Expression<>("sqrt", number);
+ public static Expression sqrt(@NonNull Expression number) {
+ return new Expression("sqrt", number);
}
/**
* Returns the square root of the input
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(sqrt(25.0f))
+ * );
+ * }
+ * </pre>
*
* @param number the number to take the square root from
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-sqrt">Style specification</a>
*/
- public static Expression<Number> sqrt(@NonNull Number number) {
+ public static Expression sqrt(@NonNull Number number) {
return sqrt(literal(number));
}
/**
* Returns the base-ten logarithm of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(log10(pi()))
+ * );
+ * }
+ * </pre>
*
* @param number the number to take base-ten logarithm from
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-log10">Style specification</a>
*/
- public static Expression<Number> log10(@NonNull Expression<Number> number) {
- return new Expression<>("log10", number);
+ public static Expression log10(@NonNull Expression number) {
+ return new Expression("log10", number);
}
/**
* Returns the base-ten logarithm of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(log10(10))
+ * );
+ * }
+ * </pre>
*
* @param number the number to take base-ten logarithm from
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-log10">Style specification</a>
*/
- public static Expression<Number> log10(@NonNull Number number) {
+ public static Expression log10(@NonNull Number number) {
return log10(literal(number));
}
/**
* Returns the natural logarithm of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(ln(pi()))
+ * );
+ * }
+ * </pre>
*
* @param number the number to take natural logarithm from
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-ln">Style specification</a>
*/
- public static Expression<Number> ln(Expression<Number> number) {
- return new Expression<>("ln", number);
+ public static Expression ln(Expression number) {
+ return new Expression("ln", number);
}
/**
* Returns the natural logarithm of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(ln(10))
+ * );
+ * }
+ * </pre>
*
* @param number the number to take natural logarithm from
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-ln">Style specification</a>
*/
- public static Expression<Number> ln(Number number) {
+ public static Expression ln(Number number) {
return ln(literal(number));
}
/**
* Returns the base-two logarithm of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(log2(pi()))
+ * );
+ * }
+ * </pre>
*
* @param number the number to take base-two logarithm from
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-log2">Style specification</a>
*/
- public static Expression<Number> log2(@NonNull Expression<Number> number) {
- return new Expression<>("log2", number);
+ public static Expression log2(@NonNull Expression number) {
+ return new Expression("log2", number);
}
/**
* Returns the base-two logarithm of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(log2(2))
+ * );
+ * }
+ * </pre>
*
* @param number the number to take base-two logarithm from
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-log2">Style specification</a>
*/
- public static Expression<Number> log2(@NonNull Number number) {
+ public static Expression log2(@NonNull Number number) {
return log2(literal(number));
}
/**
* Returns the sine of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(sin(pi()))
+ * );
+ * }
+ * </pre>
*
* @param number the number to calculate the sine for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-sin">Style specification</a>
*/
- public static Expression<Number> sin(@NonNull Expression<Number> number) {
- return new Expression<>("sin", number);
+ public static Expression sin(@NonNull Expression number) {
+ return new Expression("sin", number);
}
/**
* Returns the sine of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(sin(90.0f))
+ * );
+ * }
+ * </pre>
*
* @param number the number to calculate the sine for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-sin">Style specification</a>
*/
- public static Expression<Number> sin(@NonNull Number number) {
+ public static Expression sin(@NonNull Number number) {
return sin(literal(number));
}
/**
* Returns the cosine of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(cos(pi()))
+ * );
+ * }
+ * </pre>
*
* @param number the number to calculate the cosine for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-cos">Style specification</a>
*/
- public static Expression<Number> cos(@NonNull Expression<Number> number) {
- return new Expression<>("cos", number);
+ public static Expression cos(@NonNull Expression number) {
+ return new Expression("cos", number);
}
/**
* Returns the cosine of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(cos(0)))
+ * );
+ * }
+ * </pre>
*
* @param number the number to calculate the cosine for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-cos">Style specification</a>
*/
- public static Expression<Number> cos(@NonNull Number number) {
- return new Expression<>("cos", literal(number));
+ public static Expression cos(@NonNull Number number) {
+ return new Expression("cos", literal(number));
}
/**
* Returns the tangent of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(tan(pi()))
+ * );
+ * }
+ * </pre>
*
* @param number the number to calculate the tangent for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-tan">Style specification</a>
*/
- public static Expression<Number> tan(@NonNull Expression<Number> number) {
- return new Expression<>("tan", number);
+ public static Expression tan(@NonNull Expression number) {
+ return new Expression("tan", number);
}
/**
* Returns the tangent of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(tan(45.0f))
+ * );
+ * }
+ * </pre>
*
* @param number the number to calculate the tangent for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-tan">Style specification</a>
*/
- public static Expression<Number> tan(@NonNull Number number) {
- return new Expression<>("tan", literal(number));
+ public static Expression tan(@NonNull Number number) {
+ return new Expression("tan", literal(number));
}
/**
* Returns the arcsine of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(asin(pi()))
+ * );
+ * }
+ * </pre>
*
* @param number the number to calculate the arcsine for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-asin">Style specification</a>
*/
- public static Expression<Number> asin(@NonNull Expression<Number> number) {
- return new Expression<>("asin", number);
+ public static Expression asin(@NonNull Expression number) {
+ return new Expression("asin", number);
}
/**
* Returns the arcsine of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(asin(90))
+ * );
+ * }
+ * </pre>
*
* @param number the number to calculate the arcsine for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-asin">Style specification</a>
*/
- public static Expression<Number> asin(@NonNull Number number) {
+ public static Expression asin(@NonNull Number number) {
return asin(literal(number));
}
/**
* Returns the arccosine of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(acos(pi()))
+ * );
+ * }
+ * </pre>
*
* @param number the number to calculate the arccosine for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-acos">Style specification</a>
*/
- public static Expression<Number> acos(@NonNull Expression<Number> number) {
- return new Expression<>("acos", number);
+ public static Expression acos(@NonNull Expression number) {
+ return new Expression("acos", number);
}
/**
* Returns the arccosine of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(acos(0))
+ * );
+ * }
+ * </pre>
*
* @param number the number to calculate the arccosine for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-acos">Style specification</a>
*/
- public static Expression<Number> acos(@NonNull Number number) {
+ public static Expression acos(@NonNull Number number) {
return acos(literal(number));
}
/**
* Returns the arctangent of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(asin(pi()))
+ * );
+ * }
+ * </pre>
*
* @param number the number to calculate the arctangent for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-atan">Style specification</a>
*/
- public static Expression<Number> atan(@NonNull Expression<Number> number) {
+ public static Expression atan(@NonNull Expression number) {
return new Expression("atan", number);
}
/**
* Returns the arctangent of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(atan(90))
+ * );
+ * }
+ * </pre>
*
* @param number the number to calculate the arctangent for
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-atan">Style specification</a>
*/
- public static Expression<Number> atan(@NonNull Number number) {
+ public static Expression atan(@NonNull Number number) {
return atan(literal(number));
}
/**
* Returns the minimum value of the inputs.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(min(pi(), literal(3.14f), literal(3.15f))
+ * );
+ * }
+ * </pre>
*
* @param numbers varargs of numbers to get the minimum from
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-min">Style specification</a>
*/
- @SafeVarargs
- public static Expression<Number> min(@Size(min = 1) Expression<Number>... numbers) {
- return new Expression<>("min", numbers);
+ public static Expression min(@Size(min = 1) Expression... numbers) {
+ return new Expression("min", numbers);
}
/**
* Returns the minimum value of the inputs.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(min(3.141, 3.14f, 3.15f))
+ * );
+ * }
+ * </pre>
*
* @param numbers varargs of numbers to get the minimum from
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-min">Style specification</a>
*/
- @SuppressWarnings("unchecked")
- public static Expression<Number> min(@Size(min = 1) Number... numbers) {
- Expression<Number>[] numberExpression = (Expression<Number>[]) new Expression<?>[numbers.length];
+ public static Expression min(@Size(min = 1) Number... numbers) {
+ Expression[] numberExpression = new Expression[numbers.length];
for (int i = 0; i < numbers.length; i++) {
numberExpression[i] = literal(numbers[i]);
}
@@ -1285,33 +2253,230 @@ public class Expression<T> {
/**
* Returns the maximum value of the inputs.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(max(pi(), 3.14f, 3.15f))
+ * );
+ * }
+ * </pre>
*
* @param numbers varargs of numbers to get the maximum from
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-max">Style specification</a>
*/
- @SafeVarargs
- public static Expression<Number> max(@Size(min = 1) Expression<Number>... numbers) {
- return new Expression<>("max", numbers);
+ public static Expression max(@Size(min = 1) Expression... numbers) {
+ return new Expression("max", numbers);
}
/**
* Returns the maximum value of the inputs.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(max(3.141, 3.14f, 3.15f))
+ * );
+ * }
+ * </pre>
*
* @param numbers varargs of numbers to get the maximum from
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-max">Style specification</a>
*/
- @SuppressWarnings("unchecked")
- public static Expression<Number> max(@Size(min = 1) Number... numbers) {
- Expression<Number>[] numberExpression = (Expression<Number>[]) new Expression<?>[numbers.length];
+ public static Expression max(@Size(min = 1) Number... numbers) {
+ Expression[] numberExpression = new Expression[numbers.length];
for (int i = 0; i < numbers.length; i++) {
numberExpression[i] = literal(numbers[i]);
}
return max(numberExpression);
}
- //
- // String
- //
+ /**
+ * Rounds the input to the nearest integer.
+ * Halfway values are rounded away from zero.
+ * For example `[\"round\", -1.5]` evaluates to -2.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(round(pi()))
+ * );
+ * }
+ * </pre>
+ *
+ * @param expression number expression to round
+ * @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-round">Style specification</a>
+ */
+ public static Expression round(Expression expression) {
+ return new Expression("round", expression);
+ }
+
+ /**
+ * Rounds the input to the nearest integer.
+ * Halfway values are rounded away from zero.
+ * For example `[\"round\", -1.5]` evaluates to -2.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(round(3.14159265359f))
+ * );
+ * }
+ * </pre>
+ *
+ * @param number number to round
+ * @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-round">Style specification</a>
+ */
+ public static Expression round(Number number) {
+ return round(literal(number));
+ }
+
+ /**
+ * Returns the absolute value of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(abs(subtract(pi())))
+ * );
+ * }
+ * </pre>
+ *
+ * @param expression number expression to get absolute value from
+ * @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-abs">Style specification</a>
+ */
+ public static Expression abs(Expression expression) {
+ return new Expression("abs", expression);
+ }
+
+ /**
+ * Returns the absolute value of the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(abs(-3.14159265359f))
+ * );
+ * }
+ * </pre>
+ *
+ * @param number number to get absolute value from
+ * @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-abs">Style specification</a>
+ */
+ public static Expression abs(Number number) {
+ return abs(literal(number));
+ }
+
+ /**
+ * Returns the smallest integer that is greater than or equal to the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(ceil(pi()))
+ * );
+ * }
+ * </pre>
+ *
+ * @param expression number expression to get value from
+ * @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-abs">Style specification</a>
+ */
+ public static Expression ceil(Expression expression) {
+ return new Expression("ceil", expression);
+ }
+
+ /**
+ * Returns the smallest integer that is greater than or equal to the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(ceil(3.14159265359))
+ * );
+ * }
+ * </pre>
+ * @param number number to get value from
+ * @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-abs">Style specification</a>
+ */
+ public static Expression ceil(Number number) {
+ return ceil(literal(number));
+ }
+
+ /**
+ * Returns the largest integer that is less than or equal to the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(floor(pi()))
+ * );
+ * }
+ * </pre>
+ *
+ * @param expression number expression to get value from
+ * @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-abs">Style specification</a>
+ */
+ public static Expression floor(Expression expression) {
+ return new Expression("floor", expression);
+ }
+
+ /**
+ * Returns the largest integer that is less than or equal to the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(floor(pi()))
+ * );
+ * }
+ * </pre>
+ *
+ * @param number number to get value from
+ * @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-abs">Style specification</a>
+ */
+ public static Expression floor(Number number) {
+ return floor(literal(number));
+ }
/**
* Returns the input string converted to uppercase.
@@ -1319,12 +2484,24 @@ public class Expression<T> {
* Follows the Unicode Default Case Conversion algorithm
* and the locale-insensitive case mappings in the Unicode Character Database.
* </p>
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(upcase(get("key-to-string-value"))
+ * );
+ * }
+ * </pre>
*
* @param string the string to upcase
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-upcase">Style specification</a>
*/
- public static Expression<String> upcase(@NonNull Expression<String> string) {
- return new Expression<>("upcase", string);
+ public static Expression upcase(@NonNull Expression string) {
+ return new Expression("upcase", string);
}
/**
@@ -1333,11 +2510,23 @@ public class Expression<T> {
* Follows the Unicode Default Case Conversion algorithm
* and the locale-insensitive case mappings in the Unicode Character Database.
* </p>
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(upcase("text"))
+ * );
+ * }
+ * </pre>
*
* @param string string to upcase
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-upcase">Style specification</a>
*/
- public static Expression<String> upcase(@NonNull String string) {
+ public static Expression upcase(@NonNull String string) {
return upcase(literal(string));
}
@@ -1347,12 +2536,24 @@ public class Expression<T> {
* Follows the Unicode Default Case Conversion algorithm
* and the locale-insensitive case mappings in the Unicode Character Database.
* </p>
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(downcase(get("key-to-string-value"))
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-downcase">Style specification</a>
*/
- public static Expression<String> downcase(@NonNull Expression<String> input) {
- return new Expression<>("downcase", input);
+ public static Expression downcase(@NonNull Expression input) {
+ return new Expression("downcase", input);
}
/**
@@ -1361,44 +2562,74 @@ public class Expression<T> {
* Follows the Unicode Default Case Conversion algorithm
* and the locale-insensitive case mappings in the Unicode Character Database.
* </p>
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(upcase("key-to-string-value")
+ * );
+ * }
+ * </pre>
*
* @param input string to downcase
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-downcase">Style specification</a>
*/
- public static Expression<String> downcase(@NonNull String input) {
+ public static Expression downcase(@NonNull String input) {
return downcase(literal(input));
}
/**
* Returns a string consisting of the concatenation of the inputs.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(concat(get("key-to-string-value"), literal("other string"))
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-concat">Style specification</a>
*/
- @SafeVarargs
- public static Expression<String> concat(@NonNull Expression<String>... input) {
- return new Expression<>("concat", input);
+ public static Expression concat(@NonNull Expression... input) {
+ return new Expression("concat", input);
}
/**
* Returns a string consisting of the concatenation of the inputs.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(concat("foo", "bar"))
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-concat">Style specification</a>
*/
- @SuppressWarnings("unchecked")
- public static Expression<String> concat(@NonNull String... input) {
- Expression<String>[] stringExpression = (Expression<String>[]) new Expression<?>[input.length];
+ public static Expression concat(@NonNull String... input) {
+ Expression[] stringExpression = new Expression[input.length];
for (int i = 0; i < input.length; i++) {
stringExpression[i] = literal(input[i]);
}
return concat(stringExpression);
}
- //
- // Types
- //
-
/**
* Asserts that the input is an array (optionally with a specific item type and length).
* If, when the input expression is evaluated, it is not of the asserted type,
@@ -1406,9 +2637,10 @@ public class Expression<T> {
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-array">Style specification</a>
*/
- public static Expression<Boolean> array(@NonNull Expression input) {
- return new Expression<>("array", input);
+ public static Expression array(@NonNull Expression input) {
+ return new Expression("array", input);
}
/**
@@ -1416,55 +2648,64 @@ public class Expression<T> {
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-typeof">Style specification</a>
*/
- public static Expression<String> typeOf(@NonNull Expression input) {
- return new Expression<>("typeof", input);
+ public static Expression typeOf(@NonNull Expression input) {
+ return new Expression("typeof", input);
}
/**
* Asserts that the input value is a string.
* If multiple values are provided, each one is evaluated in order until a string value is obtained.
* If none of the inputs are strings, the expression is an error.
+ * The asserted input value is returned as result.
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-string">Style specification</a>
*/
- public static Expression<Boolean> string(@NonNull Expression input) {
- return new Expression<>("string", input);
+ public static Expression string(@NonNull Expression... input) {
+ return new Expression("string", input);
}
/**
* Asserts that the input value is a number.
* If multiple values are provided, each one is evaluated in order until a number value is obtained.
* If none of the inputs are numbers, the expression is an error.
+ * The asserted input value is returned as result.
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-number">Style specification</a>
*/
- public static Expression<Boolean> number(@NonNull Expression input) {
- return new Expression<>("number", input);
+ public static Expression number(@NonNull Expression... input) {
+ return new Expression("number", input);
}
/**
* Asserts that the input value is a boolean.
* If multiple values are provided, each one is evaluated in order until a boolean value is obtained.
* If none of the inputs are booleans, the expression is an error.
+ * The asserted input value is returned as result.
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-boolean">Style specification</a>
*/
- public static Expression<Boolean> bool(@NonNull Expression input) {
- return new Expression<>("boolean", input);
+ public static Expression bool(@NonNull Expression... input) {
+ return new Expression("boolean", input);
}
/**
* Asserts that the input value is an object. If it is not, the expression is an error
+ * The asserted input value is returned as result.
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-object">Style specification</a>
*/
- public static Expression<Boolean> object(@NonNull Expression input) {
- return new Expression<>("object", input);
+ public static Expression object(@NonNull Expression input) {
+ return new Expression("object", input);
}
/**
@@ -1476,12 +2717,24 @@ public class Expression<T> {
* where `r`, `g`, and `b` are numerals ranging from 0 to 255, and `a` ranges from 0 to 1.
* Otherwise, the input is converted to a string in the format specified by the JSON.stringify in the ECMAScript
* Language Specification.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
+ * symbolLayer.setProperties(
+ * textField(toString(get("key-to-number-value")))
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-to-string">Style specification</a>
*/
- public static Expression<String> toString(@NonNull Expression input) {
- return new Expression<>("to-string", input);
+ public static Expression toString(@NonNull Expression input) {
+ return new Expression("to-string", input);
}
/**
@@ -1491,51 +2744,83 @@ public class Expression<T> {
* If the input is a string, it is converted to a number as specified by the ECMAScript Language Specification.
* If multiple values are provided, each one is evaluated in order until the first successful conversion is obtained.
* If none of the inputs can be converted, the expression is an error.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(toNumber(get("key-to-string-value")))
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-to-number">Style specification</a>
*/
- public static Expression<Number> toNumber(@NonNull Expression input) {
- return new Expression<>("to-number", input);
+ public static Expression toNumber(@NonNull Expression input) {
+ return new Expression("to-number", input);
}
/**
- * "Converts the input value to a boolean. The result is `false` when then input is an empty string, 0, false,
+ * Converts the input value to a boolean. The result is `false` when then input is an empty string, 0, false,
* null, or NaN; otherwise it is true.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(toBool(get("key-to-value"));
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-to-boolean">Style specification</a>
*/
- public static Expression<Boolean> toBool(@NonNull Expression input) {
- return new Expression<>("to-boolean", input);
+ public static Expression toBool(@NonNull Expression input) {
+ return new Expression("to-boolean", input);
}
/**
* Converts the input value to a color. If multiple values are provided,
* each one is evaluated in order until the first successful conversion is obtained.
* If none of the inputs can be converted, the expression is an error.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new FillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(toColor(get("keyStringValue")))
+ * );
+ * }
+ * </pre>
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-to-color">Style specification</a>
*/
- public static Expression<Color> toColor(@NonNull Expression input) {
- return new Expression<>("to-color", input);
+ public static Expression toColor(@NonNull Expression input) {
+ return new Expression("to-color", input);
}
- //
- // Variable binding
- //
-
/**
* Binds input to named variables,
* which can then be referenced in the result expression using {@link #var(String)} or {@link #var(Expression)}.
*
* @param input expression input
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-let">Style specification</a>
*/
- @SafeVarargs
public static Expression let(@Size(min = 1) Expression... input) {
- return new Expression<>("let", input);
+ return new Expression("let", input);
}
/**
@@ -1543,9 +2828,10 @@ public class Expression<T> {
*
* @param expression the variable naming expression that was bound with using let
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-var">Style specification</a>
*/
- public static Expression<Object> var(@NonNull Expression<String> expression) {
- return new Expression<>("var", expression);
+ public static Expression var(@NonNull Expression expression) {
+ return new Expression("var", expression);
}
/**
@@ -1553,32 +2839,66 @@ public class Expression<T> {
*
* @param variableName the variable naming that was bound with using let
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-var">Style specification</a>
*/
public static Expression var(@NonNull String variableName) {
return var(literal(variableName));
}
- //
- // Zoom
- //
-
/**
* Gets the current zoom level.
* <p>
* Note that in style layout and paint properties,
* zoom may only appear as the input to a top-level step or interpolate expression.
* </p>
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new fillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(
+ * interpolate(
+ * exponential(0.5f), zoom(),
+ * literal(1.0f), color(Color.RED),
+ * literal(5.0f, color(Color.BLUE),
+ * literal(10.0f, color(Color.GREEN)
+ * )
+ * )
+ * );
+ * }
+ * </pre>
*
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-zoom">Style specification</a>
*/
- public static Expression<Number> zoom() {
- return new Expression<>("zoom");
+ public static Expression zoom() {
+ return new Expression("zoom");
}
- //
- // Ramps, scales, curves
- //
-
+ /**
+ * Produces a stop value to be used as part of the step expression.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(
+ * step(zoom(), literal(0.0f),
+ * stop(1.0f, 2.5f),
+ * stop(10.0f, 5.0f)
+ * )
+ * );
+ * }
+ * </pre>
+ *
+ * @param stop the stop input
+ * @param value the stop output
+ * @return the stop
+ */
public static Stop stop(@NonNull Object stop, @NonNull Object value) {
return new Stop(stop, value);
}
@@ -1589,14 +2909,30 @@ public class Expression<T> {
* Stop inputs must be numeric literals in strictly ascending order.
* Returns the output value of the stop just less than the input,
* or the first input if the input is less than the first stop.
- *
- * @param input the input value
- * @param stops pair of input and output values
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(
+ * step(zoom(), literal(0.0f),
+ * literal(1.0f), literal(2.5f),
+ * literal(10.0f), literal(5.0f)
+ * )
+ * );
+ * }
+ * </pre>
+ *
+ * @param input the input value
+ * @param defaultOutput the default output expression
+ * @param stops pair of input and output values
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step">Style specification</a>
*/
- @SafeVarargs
- public static Expression step(@NonNull Number input, @NonNull Expression expression, Expression... stops) {
- return step(literal(input), expression, stops);
+ public static Expression step(@NonNull Number input, @NonNull Expression defaultOutput, Expression... stops) {
+ return step(literal(input), defaultOutput, stops);
}
/**
@@ -1605,14 +2941,30 @@ public class Expression<T> {
* Stop inputs must be numeric literals in strictly ascending order.
* Returns the output value of the stop just less than the input,
* or the first input if the input is less than the first stop.
- *
- * @param expression the input expression
- * @param stops pair of input and output values
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(
+ * step(zoom(), literal(0.0f),
+ * literal(1.0f), literal(2.5f),
+ * literal(10.0f), literal(5.0f)
+ * )
+ * );
+ * }
+ * </pre>
+ *
+ * @param input the input expression
+ * @param defaultOutput the default output expression
+ * @param stops pair of input and output values
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step">Style specification</a>
*/
- @SafeVarargs
- public static Expression step(@NonNull Expression<Number> input, @NonNull Expression expression, Expression... stops) {
- return new Expression("step", join(new Expression[] {input, expression}, stops));
+ public static Expression step(@NonNull Expression input, @NonNull Expression defaultOutput, Expression... stops) {
+ return new Expression("step", join(new Expression[] {input, defaultOutput}, stops));
}
/**
@@ -1621,19 +2973,30 @@ public class Expression<T> {
* Stop inputs must be numeric literals in strictly ascending order.
* Returns the output value of the stop just less than the input,
* or the first input if the input is less than the first stop.
- *
- * @param input the input value
- * @param stops pair of input and output values
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(
+ * step(zoom(), literal(0.0f),
+ * stop(1, 2.5f),
+ * stop(10, 5.0f)
+ * )
+ * );
+ * }
+ * </pre>
+ *
+ * @param input the input value
+ * @param defaultOutput the default output expression
+ * @param stops pair of input and output values
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step">Style specification</a>
*/
- @SafeVarargs
- public static Expression step(@NonNull Number input, @NonNull Expression expression, Stop... stops) {
- Expression[] expressions = new Expression[stops.length * 2];
- for (int i = 0; i < stops.length; i++) {
- expressions[i * 2] = literal(stops[i].value);
- expressions[i * 2 + 1] = literal(stops[i].output);
- }
- return step(literal(input), expression, expressions);
+ public static Expression step(@NonNull Number input, @NonNull Expression defaultOutput, Stop... stops) {
+ return step(literal(input), defaultOutput, Stop.toExpressionArray(stops));
}
/**
@@ -1642,19 +3005,158 @@ public class Expression<T> {
* Stop inputs must be numeric literals in strictly ascending order.
* Returns the output value of the stop just less than the input,
* or the first input if the input is less than the first stop.
- *
- * @param input the input value
- * @param stops pair of input and output values
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(
+ * step(zoom(), literal(0.0f),
+ * stop(1, 2.5f),
+ * stop(10, 5.0f)
+ * )
+ * );
+ * }
+ * </pre>
+ *
+ * @param input the input value
+ * @param defaultOutput the default output expression
+ * @param stops pair of input and output values
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step">Style specification</a>
*/
- @SafeVarargs
- public static Expression step(@NonNull Expression<Number> input, @NonNull Expression expression, Stop... stops) {
- Expression[] expressions = new Expression[stops.length * 2];
- for (int i = 0; i < stops.length; i++) {
- expressions[i * 2] = literal(stops[i].value);
- expressions[i * 2 + 1] = literal(stops[i].output);
- }
- return step(input, expression, expressions);
+ public static Expression step(@NonNull Expression input, @NonNull Expression defaultOutput, Stop... stops) {
+ return step(input, defaultOutput, Stop.toExpressionArray(stops));
+ }
+
+ /**
+ * Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of
+ * input and output values (\"stops\"). The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * Returns the output value of the stop just less than the input,
+ * or the first input if the input is less than the first stop.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(
+ * step(1.0f, 0.0f,
+ * literal(1.0f), literal(2.5f),
+ * literal(10.0f), literal(5.0f)
+ * )
+ * );
+ * }
+ * </pre>
+ *
+ * @param input the input value
+ * @param defaultOutput the default output expression
+ * @param stops pair of input and output values
+ * @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step">Style specification</a>
+ */
+ public static Expression step(@NonNull Number input, @NonNull Number defaultOutput, Expression... stops) {
+ return step(literal(input), defaultOutput, stops);
+ }
+
+ /**
+ * Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of
+ * input and output values (\"stops\"). The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * Returns the output value of the stop just less than the input,
+ * or the first input if the input is less than the first stop.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(
+ * step(zoom(), 0.0f,
+ * literal(1.0f), literal(2.5f),
+ * literal(10.0f), literal(5.0f)
+ * )
+ * );
+ * }
+ * </pre>
+ *
+ * @param input the input expression
+ * @param defaultOutput the default output expression
+ * @param stops pair of input and output values
+ * @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step">Style specification</a>
+ */
+ public static Expression step(@NonNull Expression input, @NonNull Number defaultOutput, Expression... stops) {
+ return step(input, literal(defaultOutput), stops);
+ }
+
+ /**
+ * Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of
+ * input and output values (\"stops\"). The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * Returns the output value of the stop just less than the input,
+ * or the first input if the input is less than the first stop.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(
+ * step(zoom(), 0.0f,
+ * stop(1, 2.5f),
+ * stop(10, 5.0f)
+ * )
+ * );
+ * }
+ * </pre>
+ *
+ * @param input the input value
+ * @param defaultOutput the default output expression
+ * @param stops pair of input and output values
+ * @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step">Style specification</a>
+ */
+ public static Expression step(@NonNull Number input, @NonNull Number defaultOutput, Stop... stops) {
+ return step(literal(input), defaultOutput, Stop.toExpressionArray(stops));
+ }
+
+ /**
+ * Produces discrete, stepped results by evaluating a piecewise-constant function defined by pairs of
+ * input and output values (\"stops\"). The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
+ * Stop inputs must be numeric literals in strictly ascending order.
+ * Returns the output value of the stop just less than the input,
+ * or the first input if the input is less than the first stop.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * CircleLayer circleLayer = new CircleLayer("layer-id", "source-id");
+ * circleLayer.setProperties(
+ * circleRadius(
+ * step(zoom(), 0.0f,
+ * stop(1, 2.5f),
+ * stop(10, 5.0f)
+ * )
+ * );
+ * }
+ * </pre>
+ *
+ * @param input the input value
+ * @param defaultOutput the default output expression
+ * @param stops pair of input and output values
+ * @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step">Style specification</a>
+ */
+ public static Expression step(@NonNull Expression input, @NonNull Number defaultOutput, Stop... stops) {
+ return step(input, defaultOutput, Stop.toExpressionArray(stops));
}
/**
@@ -1662,15 +3164,33 @@ public class Expression<T> {
* The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
* Stop inputs must be numeric literals in strictly ascending order.
* The output type must be `number`, `array&lt;number&gt;`, or `color`.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new fillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(
+ * interpolate(
+ * exponential(0.5f), zoom(),
+ * literal(1.0f), color(Color.RED),
+ * literal(5.0f, color(Color.BLUE),
+ * literal(10.0f, color(Color.GREEN)
+ * )
+ * )
+ * );
+ * }
+ * </pre>
*
* @param interpolation type of interpolation
* @param number the input expression
* @param stops pair of input and output values
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-interpolate">Style specification</a>
*/
- @SafeVarargs
- public static Expression interpolate(@NonNull Expression<Interpolator> interpolation,
- @NonNull Expression<Number> number, Expression... stops) {
+ public static Expression interpolate(@NonNull Interpolator interpolation,
+ @NonNull Expression number, Expression... stops) {
return new Expression("interpolate", join(new Expression[] {interpolation, number}, stops));
}
@@ -1679,30 +3199,62 @@ public class Expression<T> {
* The `input` may be any numeric expression (e.g., `[\"get\", \"population\"]`).
* Stop inputs must be numeric literals in strictly ascending order.
* The output type must be `number`, `array&lt;number&gt;`, or `color`.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new fillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(
+ * interpolate(
+ * exponential(0.5f), zoom(),
+ * literal(1.0f), color(Color.RED),
+ * literal(5.0f, color(Color.BLUE),
+ * literal(10.0f, color(Color.GREEN)
+ * )
+ * )
+ * );
+ * }
+ * </pre>
*
* @param interpolation type of interpolation
* @param number the input expression
* @param stops pair of input and output values
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-interpolate">Style specification</a>
*/
- @SafeVarargs
- public static Expression interpolate(@NonNull Expression<Interpolator> interpolation,
- @NonNull Expression<Number> number, Stop... stops) {
- Expression[] expressions = new Expression[stops.length * 2];
- for (int i = 0; i < stops.length; i++) {
- expressions[i * 2] = literal(stops[i].value);
- expressions[i * 2 + 1] = literal(stops[i].output);
- }
- return interpolate(interpolation, number, expressions);
+ public static Expression interpolate(@NonNull Interpolator interpolation,
+ @NonNull Expression number, Stop... stops) {
+ return interpolate(interpolation, number, Stop.toExpressionArray(stops));
}
/**
* interpolates linearly between the pair of stops just less than and just greater than the input.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new fillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(
+ * interpolate(
+ * linear(), zoom(),
+ * literal(1.0f), color(Color.RED),
+ * literal(5.0f, color(Color.BLUE),
+ * literal(10.0f, color(Color.GREEN)
+ * )
+ * )
+ * );
+ * }
+ * </pre>
*
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-interpolate">Style specification</a>
*/
- public static Expression<Interpolator> linear() {
- return new Expression<>("linear");
+ public static Interpolator linear() {
+ return new Interpolator("linear");
}
/**
@@ -1710,11 +3262,30 @@ public class Expression<T> {
* `base` controls the rate at which the output increases:
* higher values make the output increase more towards the high end of the range.
* With values close to 1 the output increases linearly.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new fillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(
+ * interpolate(
+ * exponential(0.5f), zoom(),
+ * literal(1.0f), color(Color.RED),
+ * literal(5.0f, color(Color.BLUE),
+ * literal(10.0f, color(Color.GREEN)
+ * )
+ * )
+ * );
+ * }
+ * </pre>
*
* @param base value controlling the route at which the output increases
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-interpolate">Style specification</a>
*/
- public static Expression<Interpolator> exponential(@NonNull Number base) {
+ public static Interpolator exponential(@NonNull Number base) {
return exponential(literal(base));
}
@@ -1723,39 +3294,96 @@ public class Expression<T> {
* The parameter controls the rate at which the output increases:
* higher values make the output increase more towards the high end of the range.
* With values close to 1 the output increases linearly.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new fillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(
+ * interpolate(
+ * exponential(get("keyToValue"), zoom(),
+ * literal(1.0f), color(Color.RED),
+ * literal(5.0f, color(Color.BLUE),
+ * literal(10.0f, color(Color.GREEN)
+ * )
+ * )
+ * );
+ * }
+ * </pre>
*
* @param expression base number expression
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-interpolate">Style specification</a>
*/
- public static Expression<Interpolator> exponential(@NonNull Expression<Number> expression) {
- return new Expression<>("exponential", expression);
+ public static Interpolator exponential(@NonNull Expression expression) {
+ return new Interpolator("exponential", expression);
}
/**
* Interpolates using the cubic bezier curve defined by the given control points.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new fillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(
+ * interpolate(
+ * cubicBezier(0.42f, 0.0f, 1.0f, 1.0f), zoom(),
+ * literal(1.0f), color(Color.RED),
+ * literal(5.0f, color(Color.BLUE),
+ * literal(10.0f, color(Color.GREEN)
+ * )
+ * )
+ * );
+ * }
+ * </pre>
*
* @param x1 x value of the first point of a cubic bezier, ranges from 0 to 1
* @param y1 y value of the first point of a cubic bezier, ranges from 0 to 1
* @param x2 x value of the second point of a cubic bezier, ranges from 0 to 1
* @param y2 y value fo the second point of a cubic bezier, ranges from 0 to 1
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-interpolate">Style specification</a>
*/
- public static Expression<Interpolator> cubicBezier(@NonNull Expression<Number> x1, @NonNull Expression<Number> y1,
- @NonNull Expression<Number> x2, @NonNull Expression<Number> y2) {
- return new Expression<>("cubic-bezier", x1, y1, x2, y2);
+ public static Interpolator cubicBezier(@NonNull Expression x1, @NonNull Expression y1,
+ @NonNull Expression x2, @NonNull Expression y2) {
+ return new Interpolator("cubic-bezier", x1, y1, x2, y2);
}
/**
* Interpolates using the cubic bezier curve defined by the given control points.
+ * <p>
+ * Example usage:
+ * </p>
+ * <pre>
+ * {@code
+ * FillLayer fillLayer = new fillLayer("layer-id", "source-id");
+ * fillLayer.setProperties(
+ * fillColor(
+ * interpolate(
+ * cubicBezier(0.42f, 0.0f, 1.0f, 1.0f), zoom(),
+ * literal(1.0f), color(Color.RED),
+ * literal(5.0f, color(Color.BLUE),
+ * literal(10.0f, color(Color.GREEN)
+ * )
+ * )
+ * );
+ * }
+ * </pre>
*
* @param x1 x value of the first point of a cubic bezier, ranges from 0 to 1
* @param y1 y value of the first point of a cubic bezier, ranges from 0 to 1
* @param x2 x value of the second point of a cubic bezier, ranges from 0 to 1
* @param y2 y value fo the second point of a cubic bezier, ranges from 0 to 1
* @return expression
+ * @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-interpolate">Style specification</a>
*/
- public static Expression<Interpolator> cubicBezier(@NonNull Number x1, @NonNull Number y1,
- @NonNull Number x2, @NonNull Number y2) {
+ public static Interpolator cubicBezier(@NonNull Number x1, @NonNull Number y1,
+ @NonNull Number x2, @NonNull Number y2) {
return cubicBezier(literal(x1), literal(y1), literal(x2), literal(y2));
}
@@ -1776,13 +3404,59 @@ public class Expression<T> {
return output;
}
+ /**
+ * Converts the expression to Object array representation.
+ * <p>
+ * The output will later be converted to a JSON Object array.
+ * </p>
+ *
+ * @return the converted object array expression
+ */
+ @NonNull
+ public Object[] toArray() {
+ List<Object> array = new ArrayList<>();
+ array.add(operator);
+ if (arguments != null) {
+ for (Expression argument : arguments) {
+ if (argument instanceof Expression.ExpressionLiteral) {
+ array.add(toValue((ExpressionLiteral) argument));
+ } else {
+ array.add(argument.toArray());
+ }
+ }
+ }
+ return array.toArray();
+ }
+
+ /**
+ * Converts the expression value to an Object.
+ *
+ * @param expressionValue the expression value to convert
+ * @return the converted object expression
+ */
+ private Object toValue(ExpressionLiteral expressionValue) {
+ Object value = expressionValue.toValue();
+ if (value instanceof PropertyValue) {
+ throw new IllegalArgumentException("PropertyValue are not allowed as an expression literal, use value instead.");
+ } else if (value instanceof Expression.ExpressionLiteral) {
+ return toValue((ExpressionLiteral) value);
+ } else if (value instanceof Expression) {
+ return ((Expression) value).toArray();
+ }
+ return value;
+ }
+ /**
+ * Returns a string representation of the object that matches the definition set in the style specification.
+ *
+ * @return a string representation of the object.
+ */
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("[\"").append(operator).append("\"");
if (arguments != null) {
- for (Expression argument : arguments) {
+ for (Object argument : arguments) {
builder.append(", ");
if (argument instanceof ExpressionLiteral) {
builder.append(((ExpressionLiteral) argument).toValue());
@@ -1794,4 +3468,295 @@ public class Expression<T> {
builder.append("]");
return builder.toString();
}
+
+ /**
+ * Indicates whether some other object is "equal to" this one.
+ *
+ * @param o the other object
+ * @return true if equal, false if not
+ */
+ @Override
+ public boolean equals(Object o) {
+ super.equals(o);
+ if (this == o) {
+ return true;
+ }
+
+ if (o == null || !(o instanceof Expression)) {
+ return false;
+ }
+
+ Expression that = (Expression) o;
+
+ if (operator != null ? !operator.equals(that.operator) : that.operator != null) {
+ return false;
+ }
+ return Arrays.deepEquals(arguments, that.arguments);
+ }
+
+ /**
+ * Returns a hash code value for the expression.
+ *
+ * @return a hash code value for this expression
+ */
+ @Override
+ public int hashCode() {
+ int result = operator != null ? operator.hashCode() : 0;
+ result = 31 * result + Arrays.hashCode(arguments);
+ return result;
+ }
+
+ /**
+ * ExpressionLiteral wraps an object to be used as a literal in an expression.
+ * <p>
+ * ExpressionLiteral is created with {@link #literal(Number)}, {@link #literal(boolean)},
+ * {@link #literal(String)} and {@link #literal(Object)}.
+ * </p>
+ */
+ public static class ExpressionLiteral extends Expression {
+
+ protected Object literal;
+
+ /**
+ * Create an expression literal.
+ *
+ * @param object the object to be treated as literal
+ */
+ public ExpressionLiteral(@NonNull Object object) {
+ this.literal = object;
+ }
+
+ /**
+ * Get the literal object.
+ *
+ * @return the literal object
+ */
+ Object toValue() {
+ return literal;
+ }
+
+ /**
+ * Returns a string representation of the expression literal.
+ *
+ * @return a string representation of the object.
+ */
+ @Override
+ public String toString() {
+ return literal.toString();
+ }
+
+ /**
+ * Indicates whether some other object is "equal to" this one.
+ *
+ * @param o the other object
+ * @return true if equal, false if not
+ */
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ ExpressionLiteral that = (ExpressionLiteral) o;
+
+ return literal != null ? literal.equals(that.literal) : that.literal == null;
+ }
+
+ /**
+ * Returns a hash code value for the expression literal.
+ *
+ * @return a hash code value for this expression literal
+ */
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (literal != null ? literal.hashCode() : 0);
+ return result;
+ }
+ }
+
+ /**
+ * Expression interpolator type.
+ * <p>
+ * Is used for first parameter of {@link #interpolate(Interpolator, Expression, Stop...)}.
+ * </p>
+ */
+ public static class Interpolator extends Expression {
+
+ Interpolator(@NonNull String operator, @Nullable Expression... arguments) {
+ super(operator, arguments);
+ }
+ }
+
+ /**
+ * Expression array type.
+ */
+ public static class Array {
+ }
+
+ /**
+ * Expression stop type.
+ * <p>
+ * Can be used for {@link #stop(Object, Object)} as part of varargs parameter in
+ * {@link #step(Number, Expression, Stop...)} or {@link #interpolate(Interpolator, Expression, Stop...)}.
+ * </p>
+ */
+ public static class Stop {
+
+ private Object value;
+ private Object output;
+
+ Stop(Object value, Object output) {
+ this.value = value;
+ this.output = output;
+ }
+
+ /**
+ * Converts a varargs of Stops to a Expression array.
+ *
+ * @param stops the stops to convert
+ * @return the converted stops as an expression array
+ */
+ static Expression[] toExpressionArray(Stop... stops) {
+ Expression[] expressions = new Expression[stops.length * 2];
+ Stop stop;
+ Object inputValue, outputValue;
+ for (int i = 0; i < stops.length; i++) {
+ stop = stops[i];
+ inputValue = stop.value;
+ outputValue = stop.output;
+
+ if (!(inputValue instanceof Expression)) {
+ inputValue = literal(inputValue);
+ }
+
+ if (!(outputValue instanceof Expression)) {
+ outputValue = literal(outputValue);
+ }
+
+ expressions[i * 2] = (Expression) inputValue;
+ expressions[i * 2 + 1] = (Expression) outputValue;
+ }
+ return expressions;
+ }
+ }
+
+ /**
+ * Converts a JsonArray to an expression.
+ */
+ public final static class Converter {
+
+ /**
+ * Converts a JsonArray to an expression
+ *
+ * @param jsonArray the json array to convert
+ * @return the expression
+ */
+ public static Expression convert(@NonNull JsonArray jsonArray) {
+ if (jsonArray.size() == 0) {
+ throw new IllegalArgumentException("Can't convert empty jsonArray expressions");
+ }
+
+ final String operator = jsonArray.get(0).getAsString();
+ final List<Expression> arguments = new ArrayList<>();
+
+ JsonElement jsonElement;
+ for (int i = 1; i < jsonArray.size(); i++) {
+ jsonElement = jsonArray.get(i);
+ if (jsonElement instanceof JsonArray) {
+ arguments.add(convert((JsonArray) jsonElement));
+ } else if (jsonElement instanceof JsonPrimitive) {
+ arguments.add(convert((JsonPrimitive) jsonElement));
+ } else {
+ throw new RuntimeException("Unsupported expression conversion for " + jsonElement.getClass());
+ }
+ }
+ return new Expression(operator, arguments.toArray(new Expression[arguments.size()]));
+ }
+
+ /**
+ * Converts a JsonPrimitive to an expression literal
+ *
+ * @param jsonPrimitive the json primitive to convert
+ * @return the expression literal
+ */
+ private static Expression convert(@NonNull JsonPrimitive jsonPrimitive) {
+ if (jsonPrimitive.isBoolean()) {
+ return new Expression.ExpressionLiteral(jsonPrimitive.getAsBoolean());
+ } else if (jsonPrimitive.isNumber()) {
+ return new Expression.ExpressionLiteral(jsonPrimitive.getAsFloat());
+ } else if (jsonPrimitive.isString()) {
+ return new Expression.ExpressionLiteral(jsonPrimitive.getAsString());
+ } else {
+ throw new RuntimeException("Unsupported literal expression conversion for " + jsonPrimitive.getClass());
+ }
+ }
+ }
+
+ /**
+ * Expression to wrap Object[] as a literal
+ */
+ private static class ExpressionArray extends Expression {
+
+ private Object[] array;
+
+ ExpressionArray(Object[] array) {
+ this.array = array;
+ }
+
+ @NonNull
+ @Override
+ public Object[] toArray() {
+ return new Object[] {
+ "literal", array
+ };
+ }
+
+ /**
+ * Convert the expression array to a string representation.
+ *
+ * @return the string representation of the expression array
+ */
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder("[\"literal\"], [");
+ Object argument;
+ for (int i = 0; i < array.length; i++) {
+ argument = array[i];
+ if (argument instanceof String) {
+ builder.append("\"").append(argument).append("\"");
+ } else {
+ builder.append(argument);
+ }
+
+ if (i != array.length - 1) {
+ builder.append(", ");
+ }
+ }
+ builder.append("]]");
+ return builder.toString();
+ }
+ }
+
+ /**
+ * Converts an object that is a primitive array to an Object[]
+ *
+ * @param object the object to convert to an object array
+ * @return the converted object array
+ */
+ static Object[] toObjectArray(Object object) {
+ // object is a primitive array
+ int len = java.lang.reflect.Array.getLength(object);
+ Object[] objects = new Object[len];
+ for (int i = 0; i < len; i++) {
+ objects[i] = java.lang.reflect.Array.get(object, i);
+ }
+ return objects;
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/package-info.java
new file mode 100644
index 0000000000..ee2b96fa61
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/expressions/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Contains the Mapbox Maps Android Expression API classes.
+ */
+package com.mapbox.mapboxsdk.style.expressions;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CameraFunction.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CameraFunction.java
deleted file mode 100644
index bb87fe8a39..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CameraFunction.java
+++ /dev/null
@@ -1,50 +0,0 @@
-package com.mapbox.mapboxsdk.style.functions;
-
-import android.support.annotation.Keep;
-import android.support.annotation.NonNull;
-
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
-
-/**
- * Camera function. Functions that take camera properties as input (zoom for now)
- * <p>
- * Zoom functions allow the appearance of a map feature to change with map’s zoom level.
- * 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 level and the second is
- * a function output value.
- *
- * @param <I> the input type
- * @param <O> the output type
- * @see Function#zoom
- */
-public class CameraFunction<I extends Number, O> extends Function<I, O> {
-
- /**
- * Create an exponential camera function
- *
- * @param stops @see {@link com.mapbox.mapboxsdk.style.functions.stops.Stops#exponential(float, Stop[])}
- */
- CameraFunction(@NonNull ExponentialStops<I, O> stops) {
- super(stops);
- }
-
- /**
- * Create an interval camera function
- *
- * @param stops @see {@link com.mapbox.mapboxsdk.style.functions.stops.Stops#interval(Stop[])}
- */
- CameraFunction(@NonNull IntervalStops<I, O> stops) {
- super(stops);
- }
-
- /**
- * JNI constructor
- */
- @Keep
- private CameraFunction(Stops<I, O> stops) {
- super(stops);
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CompositeFunction.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CompositeFunction.java
deleted file mode 100644
index 15e4474105..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/CompositeFunction.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.mapbox.mapboxsdk.style.functions;
-
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-
-import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
-import com.mapbox.mapboxsdk.style.layers.PropertyValue;
-
-import java.util.Map;
-
-/**
- * Composite functions combine Camera and SourceFunctions.
- * <p>
- * Composite functions allow the appearance of a map feature to change with both its
- * properties and zoom. Each stop is an array with two elements, the first is an object
- * with a property input value and a zoom, and the second is a function output value. Note
- * that support for property functions is not yet complete.
- *
- * @param <Z> the zoom type (usually Float)
- * @param <I> the input type (the feature property type)
- * @param <O> the output type (the property type)
- * @see Function#composite
- */
-public class CompositeFunction<Z extends Number, I, O> extends Function<Stop.CompositeValue<Z, I>, O> {
-
- private final String property;
- private PropertyValue<O> defaultValue;
-
- CompositeFunction(@NonNull String property,
- @NonNull CategoricalStops<Stop.CompositeValue<Z, I>, O> stops) {
- this(null, property, stops);
- }
-
- CompositeFunction(@NonNull String property,
- @NonNull ExponentialStops<Stop.CompositeValue<Z, I>, O> stops) {
- this(null, property, stops);
- }
-
- CompositeFunction(@NonNull String property,
- @NonNull IntervalStops<Stop.CompositeValue<Z, I>, O> stops) {
- this(null, property, stops);
- }
-
-
- /**
- * JNI Constructor
- */
- private CompositeFunction(@Nullable O defaultValue, @NonNull String property,
- @NonNull Stops<Stop.CompositeValue<Z, I>, O> stops) {
- super(stops);
- this.defaultValue = new PropertyValue<>(property, defaultValue);
- this.property = property;
- }
-
- /**
- * Set the default value
- *
- * @param defaultValue the default value to use when no other applies
- * @return this (for chaining)
- */
- public CompositeFunction<Z, I, O> withDefaultValue(PropertyValue<O> defaultValue) {
- this.defaultValue = defaultValue;
- return this;
- }
-
- /**
- * @return the defaultValue
- */
- @Nullable
- public PropertyValue<O> getDefaultValue() {
- return defaultValue;
- }
-
- /**
- * INTERNAL USAGE ONLY
- *
- * @return the feature property name
- */
- public String getProperty() {
- return property;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Map<String, Object> toValueObject() {
- Map<String, Object> valueObject = super.toValueObject();
- valueObject.put(PROPERTY_KEY, property);
- if (defaultValue != null) {
- valueObject.put(DEFAULT_VALUE_KEY, defaultValue.value);
- }
- return valueObject;
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/Function.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/Function.java
deleted file mode 100644
index e7bb52ebb3..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/Function.java
+++ /dev/null
@@ -1,300 +0,0 @@
-package com.mapbox.mapboxsdk.style.functions;
-
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-
-import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
-
-import java.util.Map;
-
-import timber.log.Timber;
-
-/**
- * Functions are used to change properties in relation to the state of the map.
- * <p>
- * The value for any layout or paint property may be specified as a function. Functions allow you to
- * make the appearance of a map feature change with the current zoom level and/or the feature's properties.
- *
- * @param <I> the function's input type
- * @param <O> the target property's value type. Make sure it matches.
- * @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#types-function">The style specification</a>
- */
-public class Function<I, O> {
-
- static final String PROPERTY_KEY = "property";
- static final String DEFAULT_VALUE_KEY = "default";
-
- /**
- * Create an exponential {@link CameraFunction}
- * <p>
- * 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 <Z> the zoom level type (Float, Integer)
- * @param <O> the property type
- * @param stops the stops implementation that define the function. @see {@link Stops#exponential(Stop[])}
- * @return the {@link CameraFunction}
- * @see CameraFunction
- * @see ExponentialStops
- * @see Stops#exponential(Stop[])
- * @see Stops#exponential(Stop[])
- * @see Stop#stop
- */
- public static <Z extends Number, O> CameraFunction<Z, O> zoom(@NonNull ExponentialStops<Z, O> stops) {
- return new CameraFunction<>(stops);
- }
-
- /**
- * Create an interval {@link CameraFunction}
- * <p>
- * 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 <Z> the zoom level type (Float, Integer)
- * @param <O> the property type
- * @param stops the stops implementation that define the function. @see {@link Stops#interval(Stop[])}
- * @return the {@link CameraFunction}
- * @see CameraFunction
- * @see IntervalStops
- * @see Stops#interval(Stop[])
- * @see Stop#stop
- */
- public static <Z extends Number, O> CameraFunction<Z, O> zoom(@NonNull IntervalStops<Z, O> stops) {
- return new CameraFunction<>(stops);
- }
-
- /**
- * Create an exponential {@link SourceFunction}
- * <p>
- * Source functions allow the appearance of a map feature to change with
- * its properties. Source functions can be used to visually differentiate
- * types of features within the same layer or create data visualizations.
- * Each stop is an array with two elements, the first is a property input
- * value and the second is a function output value. Note that support for
- * property functions is not available across all properties and platforms
- * at this time.
- *
- * @param property the feature property name
- * @param stops the stops
- * @param <I> the function input type
- * @param <O> the function output type
- * @return the {@link SourceFunction}
- * @see SourceFunction
- * @see ExponentialStops
- * @see Stops#exponential(Stop[])
- * @see Stop#stop
- */
- public static <I, O> SourceFunction<I, O> property(@NonNull String property, @NonNull ExponentialStops<I, O> stops) {
- return new SourceFunction<>(property, stops);
- }
-
- /**
- * Create an identity {@link SourceFunction}
- * <p>
- * Source functions allow the appearance of a map feature to change with
- * its properties. Source functions can be used to visually differentiate
- * types of features within the same layer or create data visualizations.
- * Each stop is an array with two elements, the first is a property input
- * value and the second is a function output value. Note that support for
- * property functions is not available across all properties and platforms
- * at this time.
- *
- * @param property the feature property name
- * @param stops the stops
- * @param <T> the function input/output type
- * @return the {@link SourceFunction}
- * @see SourceFunction
- * @see IdentityStops
- * @see Stops#identity()
- * @see Stop#stop
- */
- public static <T> SourceFunction<T, T> property(@NonNull String property, @NonNull IdentityStops<T> stops) {
- return new SourceFunction<>(property, stops);
- }
-
- /**
- * Create an interval {@link SourceFunction}
- * <p>
- * Source functions allow the appearance of a map feature to change with
- * its properties. Source functions can be used to visually differentiate
- * types of features within the same layer or create data visualizations.
- * Each stop is an array with two elements, the first is a property input
- * value and the second is a function output value. Note that support for
- * property functions is not available across all properties and platforms
- * at this time.
- *
- * @param property the feature property name
- * @param stops the stops
- * @param <I> the function input type
- * @param <O> the function output type
- * @return the {@link SourceFunction}
- * @see SourceFunction
- * @see IntervalStops
- * @see Stops#interval(Stop[])
- * @see Stop#stop
- */
- public static <I, O> SourceFunction<I, O> property(@NonNull String property, @NonNull IntervalStops<I, O> stops) {
- return new SourceFunction<>(property, stops);
- }
-
- /**
- * Create an categorical {@link SourceFunction}
- * <p>
- * Source functions allow the appearance of a map feature to change with
- * its properties. Source functions can be used to visually differentiate
- * types of features within the same layer or create data visualizations.
- * Each stop is an array with two elements, the first is a property input
- * value and the second is a function output value. Note that support for
- * property functions is not available across all properties and platforms
- * at this time.
- *
- * @param property the feature property name
- * @param stops the stops
- * @param <I> the function input type
- * @param <O> the function output type
- * @return the {@link SourceFunction}
- * @see SourceFunction
- * @see CategoricalStops
- * @see Stops#categorical(Stop[])
- * @see Stop#stop
- */
- public static <I, O> SourceFunction<I, O> property(@NonNull String property, @NonNull CategoricalStops<I, O> stops) {
- return new SourceFunction<>(property, stops);
- }
-
- /**
- * Create a composite, categorical function.
- * <p>
- * Composite functions allow the appearance of a map feature to change with both its
- * properties and zoom. Each stop is an array with two elements, the first is an object
- * with a property input value and a zoom, and the second is a function output value. Note
- * that support for property functions is not yet complete.
- *
- * @param property the feature property name for the source part of the function
- * @param stops the stops
- * @param <Z> the zoom function input type (Float usually)
- * @param <I> the function input type for the source part of the function
- * @param <O> the function output type
- * @return the {@link CompositeFunction}
- * @see CompositeFunction
- * @see CategoricalStops
- * @see Stops#categorical(Stop[])
- * @see Stop#stop
- */
- public static <Z extends Number, I, O> CompositeFunction<Z, I, O> composite(
- @NonNull String property,
- @NonNull CategoricalStops<Stop.CompositeValue<Z, I>, O> stops) {
-
- return new CompositeFunction<>(property, stops);
- }
-
- /**
- * Create a composite, exponential function.
- * <p>
- * Composite functions allow the appearance of a map feature to change with both its
- * properties and zoom. Each stop is an array with two elements, the first is an object
- * with a property input value and a zoom, and the second is a function output value. Note
- * that support for property functions is not yet complete.
- *
- * @param property the feature property name for the source part of the function
- * @param stops the stops
- * @param <Z> the zoom function input type (Float usually)
- * @param <I> the function input type for the source part of the function
- * @param <O> the function output type
- * @return the {@link CompositeFunction}
- * @see CompositeFunction
- * @see ExponentialStops
- * @see Stops#exponential(Stop[])
- * @see Stop#stop
- */
- public static <Z extends Number, I, O> CompositeFunction<Z, I, O> composite(
- @NonNull String property,
- @NonNull ExponentialStops<Stop.CompositeValue<Z, I>, O> stops) {
-
- return new CompositeFunction<>(property, stops);
- }
-
- /**
- * Create a composite, interval function.
- * <p>
- * Composite functions allow the appearance of a map feature to change with both its
- * properties and zoom. Each stop is an array with two elements, the first is an object
- * with a property input value and a zoom, and the second is a function output value. Note
- * that support for property functions is not yet complete.
- *
- * @param property the feature property name for the source part of the function
- * @param stops the stops
- * @param <Z> the zoom function input type (Float usually)
- * @param <I> the function input type for the source part of the function
- * @param <O> the function output type
- * @return the {@link CompositeFunction}
- * @see CompositeFunction
- * @see IntervalStops
- * @see Stops#interval(Stop[])
- * @see Stop#stop
- */
- public static <Z extends Number, I, O> CompositeFunction<Z, I, O> composite(
- @NonNull String property,
- @NonNull IntervalStops<Stop.CompositeValue<Z, I>, O> stops) {
-
- return new CompositeFunction<>(property, stops);
- }
-
- // Class definition //
-
- private final Stops<I, O> stops;
-
- /**
- * JNI Cosntructor for implementation classes
- *
- * @param stops the stops
- */
- Function(@NonNull Stops<I, O> stops) {
- this.stops = stops;
- }
-
- /**
- * @return the stops in this function
- */
- public Stops getStops() {
- return stops;
- }
-
- /**
- * Convenience method
- *
- * @param <S> the Stops implementation type
- * @return the Stops implementation or null when the wrong type is specified
- */
- @Nullable
- public <S extends Stops> S getStopsAs() {
- try {
- // noinspection unchecked
- return (S) stops;
- } catch (ClassCastException exception) {
- Timber.e(exception, "Stops: %s is a different type: ", stops.getClass());
- return null;
- }
- }
-
- /**
- * INTERNAL USAGE ONLY
- *
- * @return a value object representation for core conversion
- */
- public Map<String, Object> toValueObject() {
- return stops.toValueObject();
- }
-
- @Override
- public String toString() {
- return String.format("%s: %s", getClass().getSimpleName(), stops);
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/SourceFunction.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/SourceFunction.java
deleted file mode 100644
index 33f436ae71..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/SourceFunction.java
+++ /dev/null
@@ -1,85 +0,0 @@
-package com.mapbox.mapboxsdk.style.functions;
-
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
-import com.mapbox.mapboxsdk.style.layers.PropertyValue;
-
-import java.util.Map;
-
-/**
- * Source functions take Feature property names as input.
- * <p>
- * Source functions allow the appearance of a map feature to change with
- * its properties. Source functions can be used to visually differentiate
- * types of features within the same layer or create data visualizations.
- * Each stop is an array with two elements, the first is a property input
- * value and the second is a function output value. Note that support for
- * property functions is not available across all properties and platforms
- * at this time.
- *
- * @param <I> the input type
- * @param <O> the output type
- * @see Function#property
- */
-public class SourceFunction<I, O> extends Function<I, O> {
-
- private final String property;
- private PropertyValue<O> defaultValue;
-
- SourceFunction(@NonNull String property, @NonNull Stops<I, O> stops) {
- this(null, property, stops);
- }
-
- /**
- * JNI Constructor
- */
- private SourceFunction(@Nullable O defaultValue, @NonNull String property, @NonNull Stops<I, O> stops) {
- super(stops);
- this.property = property;
- this.defaultValue = defaultValue != null ? new PropertyValue<>(property, defaultValue) : null;
- }
-
-
- /**
- * INTERNAL USAGE ONLY
- *
- * @return The feature property name
- */
- public String getProperty() {
- return property;
- }
-
- /**
- * Set the default value
- *
- * @param defaultValue the default value to use when no other applies
- * @return this (for chaining)
- */
- public SourceFunction<I, O> withDefaultValue(PropertyValue<O> defaultValue) {
- this.defaultValue = defaultValue;
- return this;
- }
-
- /**
- * @return the defaultValue
- */
- @Nullable
- public PropertyValue<O> getDefaultValue() {
- return defaultValue;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Map<String, Object> toValueObject() {
- Map<String, Object> valueObject = super.toValueObject();
- valueObject.put(PROPERTY_KEY, property);
- if (defaultValue != null) {
- valueObject.put(DEFAULT_VALUE_KEY, defaultValue.value);
- }
- return valueObject;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/package-info.java
deleted file mode 100644
index 6979676c9e..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * Contains the Mapbox Maps Android Style Function API classes.
- *
- * @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#types-function">The style specification</a>
- */
-package com.mapbox.mapboxsdk.style.functions;
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/CategoricalStops.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/CategoricalStops.java
deleted file mode 100644
index f9b2929350..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/CategoricalStops.java
+++ /dev/null
@@ -1,64 +0,0 @@
-package com.mapbox.mapboxsdk.style.functions.stops;
-
-import android.support.annotation.NonNull;
-import android.support.annotation.Size;
-
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * {@link Stops} implementation for categorical functions
- *
- * @param <I> the {@link Stop} input type
- * @param <O> the {@link Stop} output type
- */
-public class CategoricalStops<I, O> extends IterableStops<I, O, Stop<I, O>> {
-
- private final Stop<I, O>[] stops;
-
- /**
- * Create a categorical {@link Stops} implementation. Use through {@link Stops#categorical(Stop[])}
- *
- * @param stops the stops
- */
- @SafeVarargs
- public CategoricalStops(@NonNull @Size(min = 1) Stop<I, O>... stops) {
- this.stops = stops;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Map<String, Object> toValueObject() {
- Map<String, Object> map = super.toValueObject();
- map.put("stops", toValueObjects(stops));
- return map;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getTypeName() {
- return "categorical";
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Iterator<Stop<I, O>> iterator() {
- return Arrays.asList(stops).iterator();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int size() {
- return stops.length;
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/ExponentialStops.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/ExponentialStops.java
deleted file mode 100644
index d47aa1fc91..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/ExponentialStops.java
+++ /dev/null
@@ -1,97 +0,0 @@
-package com.mapbox.mapboxsdk.style.functions.stops;
-
-import android.support.annotation.NonNull;
-import android.support.annotation.Size;
-
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * The {@link Stops} implementation for exponential functions
- *
- * @param <I> the input type
- * @param <O> the output type
- */
-public class ExponentialStops<I, O> extends IterableStops<I, O, Stop<I, O>> {
-
- private float base;
- private final Stop<I, O>[] stops;
-
- /**
- * Create exponential stops with an explicit base. Use through {@link Stops#exponential(Stop[])}
- *
- * @param base The exponential base of the interpolation curve. It controls the rate at which the function output
- * increases. Higher values make the output increase more towards the high end of the range.
- * With values close to 1 the output increases linearly.
- * @param stops the stops
- */
- @SafeVarargs
- public ExponentialStops(Float base, @NonNull @Size(min = 1) Stop<I, O>... stops) {
- this.base = base != null ? base : 1.0f;
- this.stops = stops;
- }
-
- /**
- * Create exponential stops without an explicit base. Use through {@link Stops#exponential(Stop[])}
- *
- * @param stops the stops
- */
- @SafeVarargs
- public ExponentialStops(@NonNull @Size(min = 1) Stop<I, O>... stops) {
- this(null, stops);
- }
-
- /**
- * Set the exponential base
- *
- * @param base the base to use in the exponential function
- * @return this (for chaining)
- */
- public ExponentialStops<I, O> withBase(float base) {
- this.base = base;
- return this;
- }
-
- /**
- * @return The exponential base
- */
- public float getBase() {
- return base;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Map<String, Object> toValueObject() {
- Map<String, Object> map = super.toValueObject();
- map.put("base", base);
- map.put("stops", toValueObjects(stops));
- return map;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getTypeName() {
- return "exponential";
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Iterator<Stop<I, O>> iterator() {
- return Arrays.asList(stops).iterator();
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public int size() {
- return stops.length;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/IdentityStops.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/IdentityStops.java
deleted file mode 100644
index 2c0b198dc2..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/IdentityStops.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.mapbox.mapboxsdk.style.functions.stops;
-
-/**
- * The {@link Stops} implementation for identity functions
- *
- * @param <T> the input/output type
- */
-public class IdentityStops<T> extends Stops<T, T> {
-
- /**
- * {@inheritDoc}
- */
- @Override
- protected String getTypeName() {
- return "identity";
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/IntervalStops.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/IntervalStops.java
deleted file mode 100644
index 9d95b3f8c1..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/IntervalStops.java
+++ /dev/null
@@ -1,58 +0,0 @@
-package com.mapbox.mapboxsdk.style.functions.stops;
-
-import android.support.annotation.NonNull;
-import android.support.annotation.Size;
-
-import java.util.Arrays;
-import java.util.Iterator;
-import java.util.Map;
-
-/**
- * The {@link Stops} implementation for interval functions
- *
- * @param <I> the input type
- * @param <O> the output type
- */
-public class IntervalStops<I, O> extends IterableStops<I, O, Stop<I, O>> {
-
- private final Stop<I, O>[] stops;
-
- @SafeVarargs
- public IntervalStops(@NonNull @Size(min = 1) Stop<I, O>... stops) {
- this.stops = stops;
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public String getTypeName() {
- return "interval";
- }
-
- /**
- * {@inheritDoc}
- */
- @Override
- public Map<String, Object> toValueObject() {
- Map<String, Object> map = super.toValueObject();
- map.put("stops", toValueObjects(stops));
- return map;
- }
-
- /**
- * @return an {@link Iterator} for the contained stops
- */
- @Override
- public Iterator<Stop<I, O>> iterator() {
- return Arrays.asList(stops).iterator();
- }
-
- /**
- * @return The number of contained stops
- */
- @Override
- public int size() {
- return stops.length;
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/IterableStops.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/IterableStops.java
deleted file mode 100644
index 8c5a6e8913..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/IterableStops.java
+++ /dev/null
@@ -1,52 +0,0 @@
-package com.mapbox.mapboxsdk.style.functions.stops;
-
-import java.util.Iterator;
-
-/**
- * Base class for {@link Stops} implementations with a collection of stops
- *
- * @param <I> the {@link Stops} input type
- * @param <O> the {@link Stops} output type
- * @param <S> the {@link Iterable} element type (usually {@link Stop})
- */
-public abstract class IterableStops<I, O, S> extends Stops<I, O> implements Iterable<S> {
-
- /**
- * @return The size of the contained stops collection
- */
- public abstract int size();
-
- /**
- * Convenience function to toValueObjects an array of stops to an array of value objects
- *
- * @param stops the stops to toValueObjects
- * @return the stops as value objects
- */
- Object[] toValueObjects(Stop<I, O>[] stops) {
- if (stops != null) {
- Object[] stopsValue = new Object[stops.length];
-
- for (int i = 0; i < stopsValue.length; i++) {
- Stop stop = stops[i];
- stopsValue[i] = stop.toValueObject();
- }
- return stopsValue;
- }
-
- return null;
- }
-
- @Override
- public String toString() {
- StringBuilder buffer = new StringBuilder();
- Iterator<S> iterator = iterator();
- while (iterator.hasNext()) {
- S stop = iterator.next();
- buffer.append(stop);
- if (iterator.hasNext()) {
- buffer.append(",");
- }
- }
- return String.format("%s: [%s]", super.toString(), buffer.toString());
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/Stop.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/Stop.java
deleted file mode 100644
index 72164f4c4b..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/Stop.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package com.mapbox.mapboxsdk.style.functions.stops;
-
-import com.mapbox.mapboxsdk.style.functions.Function;
-import com.mapbox.mapboxsdk.style.layers.PropertyValue;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * A stop represents a certain point in the range of this function
- *
- * @param <I> input the stop (function) input type
- * @param <O> output the stop (function) output type
- * @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#types-function">The style specification</a>
- */
-public class Stop<I, O> {
- /**
- * Creates a {@link Stop} to use in a {@link Function}
- *
- * @param in the input for the stop
- * @param output the output for the stop
- * @param <I> the input property type
- * @param <O> the output property type
- * @return the {@link Stop}
- */
- public static <I, O> Stop<I, O> stop(I in, PropertyValue<O> output) {
- return new Stop<>(in, output.value);
- }
-
- /**
- * Create a composite {@link Stop} for use in a {@link com.mapbox.mapboxsdk.style.functions.CompositeFunction}
- *
- * @param zoom the zoom input
- * @param value the feature property input
- * @param output the output for the stop
- * @param <Z> the zoom type
- * @param <I> the feature property input type
- * @param <O> the output property type
- * @return the {@link Stop}
- * @see Function#composite(String, ExponentialStops)
- */
- public static <Z extends Number, I, O> Stop<Stop.CompositeValue<Z, I>, O> stop(Z zoom,
- I value,
- PropertyValue<O> output) {
- return new Stop<>(new Stop.CompositeValue<>(zoom, value), output.value);
- }
-
- /**
- * Represents a composite input value for composite functions (eg zoom and feature property value)
- *
- * @param <Z> the zoom input type (typically Float)
- * @param <V> the feature property input type
- */
- public static class CompositeValue<Z extends Number, V> {
- public final Z zoom;
- public final V value;
-
- CompositeValue(Z zoom, V value) {
- this.zoom = zoom;
- this.value = value;
- }
-
- /**
- * INTERNAL USAGE ONLY
- *
- * @return the value object representation for core conversion
- */
- Map<String, Object> toValueObject() {
- HashMap<String, Object> map = new HashMap<>();
- map.put("zoom", zoom);
- map.put("value", value);
- return map;
- }
-
- @Override
- public String toString() {
- return String.format("[zoom: %s, value: %s]", zoom, value);
- }
- }
-
- /**
- * The input type
- */
- public final I in;
-
- /**
- * The output type
- */
- public final O out;
-
- Stop(I in, O out) {
- this.in = in;
- this.out = out;
- }
-
- /**
- * INTERNAL USAGE ONLY
- *
- * @return an array representation of the Stop
- */
- Object[] toValueObject() {
- return new Object[] {in instanceof CompositeValue ? ((CompositeValue) in).toValueObject() : in, out};
- }
-
- @Override
- public String toString() {
- return String.format("[%s, %s]", in, out);
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/Stops.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/Stops.java
deleted file mode 100644
index af4f53c072..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/Stops.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.mapbox.mapboxsdk.style.functions.stops;
-
-import android.support.annotation.CallSuper;
-import android.support.annotation.NonNull;
-import android.support.annotation.Size;
-
-import java.util.HashMap;
-import java.util.Map;
-
-/**
- * The base class for different stops implementations
- *
- * @param <I> the input type
- * @param <O> the output type
- * @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#types-function">The style specification</a>
- */
-public abstract class Stops<I, O> {
-
- /**
- * Convenience method for use in function declarations
- *
- * @param stops the collections of discrete stops
- * @param <I> the Stops input type
- * @param <O> the Stops output type
- * @return the {@link Stops} implementation
- * @see Stop#stop
- * @see CategoricalStops
- */
- @SafeVarargs
- public static <I, O> CategoricalStops<I, O> categorical(@NonNull @Size(min = 1) Stop<I, O>... stops) {
- return new CategoricalStops<>(stops);
- }
-
- /**
- * Convenience method for use in function declarations
- *
- * @param stops the collections of discrete stops
- * @param <I> the Stops input type
- * @param <O> the Stops output type
- * @return the {@link Stops} implementation
- * @see Stop#stop
- * @see ExponentialStops
- */
- @SafeVarargs
- public static <I, O> ExponentialStops<I, O> exponential(@NonNull @Size(min = 1) Stop<I, O>... stops) {
- return new ExponentialStops<>(stops);
- }
-
- /**
- * Convenience method for use in function declarations
- *
- * @param <T> the Stops input/output type
- * @return the {@link IdentityStops} implementation
- * @see Stop#stop
- * @see IdentityStops
- */
- public static <T> IdentityStops<T> identity() {
- return new IdentityStops<>();
- }
-
- /**
- * Convenience method for use in function declarations
- *
- * @param stops the collections of discrete stops
- * @param <I> the Stops input type
- * @param <O> the Stops output type
- * @return the {@link Stops} implementation
- * @see Stop#stop
- * @see IntervalStops
- */
- @SafeVarargs
- public static <I, O> IntervalStops<I, O> interval(@NonNull @Size(min = 1) Stop<I, O>... stops) {
- return new IntervalStops<>(stops);
- }
-
- /**
- * INTERNAL USAGE ONLY
- *
- * @return the value object representation for conversion to core
- */
- @CallSuper
- public Map<String, Object> toValueObject() {
- HashMap<String, Object> map = new HashMap<>();
- map.put("type", getTypeName());
- return map;
- }
-
- /**
- * INTERNAL USAGE ONLY
- *
- * @return the unique type name as a string according to the style specification
- */
- protected abstract String getTypeName();
-
- @Override
- public String toString() {
- return getTypeName();
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/package-info.java
deleted file mode 100644
index fa388a9589..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/functions/stops/package-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-/**
- * Contains the Mapbox Maps Android Style Function Stop implementation API classes.
- *
- * @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#types-function">The style specification</a>
- */
-package com.mapbox.mapboxsdk.style.functions.stops;
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 978fa29ef8..60c2aa907b 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
@@ -4,10 +4,13 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
+import com.google.gson.JsonArray;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
/**
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 10663142b5..94929398d5 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
@@ -4,10 +4,13 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
+import com.google.gson.JsonArray;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
/**
@@ -69,26 +72,41 @@ public class CircleLayer extends Layer {
}
/**
- * Set a single filter.
+ * Set a single expression filter.
*
- * @param filter the filter to set
+ * @param filter the expression filter to set
*/
- public void setFilter(Filter.Statement filter) {
+ public void setFilter(Expression filter) {
nativeSetFilter(filter.toArray());
}
/**
- * Set a single filter.
+ * Set a single expression filter.
*
- * @param filter the filter to set
+ * @param filter the expression filter to set
* @return This
*/
- public CircleLayer withFilter(Filter.Statement filter) {
+ public CircleLayer withFilter(Expression filter) {
setFilter(filter);
return this;
}
/**
+ * Get a single expression filter.
+ *
+ * @return the expression filter to get
+ */
+ @Nullable
+ public Expression getFilter() {
+ Expression expression = null;
+ JsonArray array = (JsonArray) nativeGetFilter();
+ if (array != null) {
+ expression = Expression.Converter.convert(array);
+ }
+ return expression;
+ }
+
+ /**
* Set a property or properties.
*
* @param properties the var-args properties
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 f77e7280f0..a0ba1e2159 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
@@ -9,20 +9,8 @@ package com.mapbox.mapboxsdk.style.layers;
public class CustomLayer extends Layer {
public CustomLayer(String id,
- long context,
- long initializeFunction,
- long renderFunction,
- long deinitializeFunction) {
- this(id, context, initializeFunction, renderFunction, 0L, deinitializeFunction);
- }
-
- public CustomLayer(String id,
- long context,
- long initializeFunction,
- long renderFunction,
- long contextLostFunction,
- long deinitializeFunction) {
- initialize(id, initializeFunction, renderFunction, contextLostFunction, deinitializeFunction, context);
+ long host) {
+ initialize(id, host);
}
public CustomLayer(long nativePtr) {
@@ -33,9 +21,7 @@ public class CustomLayer extends Layer {
nativeUpdate();
}
- protected native void initialize(String id, long initializeFunction, long renderFunction,
- long contextLostFunction, long deinitializeFunction,
- long context);
+ protected native void initialize(String id, long host);
protected native void nativeUpdate();
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer.java
index 6772da73b1..29e2b49d76 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer.java
@@ -4,10 +4,13 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
+import com.google.gson.JsonArray;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
/**
@@ -69,26 +72,41 @@ public class FillExtrusionLayer extends Layer {
}
/**
- * Set a single filter.
+ * Set a single expression filter.
*
- * @param filter the filter to set
+ * @param filter the expression filter to set
*/
- public void setFilter(Filter.Statement filter) {
+ public void setFilter(Expression filter) {
nativeSetFilter(filter.toArray());
}
/**
- * Set a single filter.
+ * Set a single expression filter.
*
- * @param filter the filter to set
+ * @param filter the expression filter to set
* @return This
*/
- public FillExtrusionLayer withFilter(Filter.Statement filter) {
+ public FillExtrusionLayer withFilter(Expression filter) {
setFilter(filter);
return this;
}
/**
+ * Get a single expression filter.
+ *
+ * @return the expression filter to get
+ */
+ @Nullable
+ public Expression getFilter() {
+ Expression expression = null;
+ JsonArray array = (JsonArray) nativeGetFilter();
+ if (array != null) {
+ expression = Expression.Converter.convert(array);
+ }
+ return expression;
+ }
+
+ /**
* Set a property or properties.
*
* @param properties the var-args properties
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 3719ae9e1b..ed780811c0 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
@@ -4,10 +4,13 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
+import com.google.gson.JsonArray;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
/**
@@ -69,26 +72,41 @@ public class FillLayer extends Layer {
}
/**
- * Set a single filter.
+ * Set a single expression filter.
*
- * @param filter the filter to set
+ * @param filter the expression filter to set
*/
- public void setFilter(Filter.Statement filter) {
+ public void setFilter(Expression filter) {
nativeSetFilter(filter.toArray());
}
/**
- * Set a single filter.
+ * Set a single expression filter.
*
- * @param filter the filter to set
+ * @param filter the expression filter to set
* @return This
*/
- public FillLayer withFilter(Filter.Statement filter) {
+ public FillLayer withFilter(Expression filter) {
setFilter(filter);
return this;
}
/**
+ * Get a single expression filter.
+ *
+ * @return the expression filter to get
+ */
+ @Nullable
+ public Expression getFilter() {
+ Expression expression = null;
+ JsonArray array = (JsonArray) nativeGetFilter();
+ if (array != null) {
+ expression = Expression.Converter.convert(array);
+ }
+ return expression;
+ }
+
+ /**
* Set a property or properties.
*
* @param properties the var-args properties
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
deleted file mode 100644
index 4dbb461e4c..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Filter.java
+++ /dev/null
@@ -1,230 +0,0 @@
-package com.mapbox.mapboxsdk.style.layers;
-
-import java.util.ArrayList;
-import java.util.Collections;
-
-/**
- * Utility to build filter expressions more easily.
- *
- * @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#types-filter">The online documentation</a>
- */
-public class Filter {
-
- /**
- * Base 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);
- }
-
- /**
- * 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/HeatmapLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/HeatmapLayer.java
index 6b8fd65def..42b4210710 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/HeatmapLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/HeatmapLayer.java
@@ -4,10 +4,13 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
+import com.google.gson.JsonArray;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
/**
@@ -69,26 +72,41 @@ public class HeatmapLayer extends Layer {
}
/**
- * Set a single filter.
+ * Set a single expression filter.
*
- * @param filter the filter to set
+ * @param filter the expression filter to set
*/
- public void setFilter(Filter.Statement filter) {
+ public void setFilter(Expression filter) {
nativeSetFilter(filter.toArray());
}
/**
- * Set a single filter.
+ * Set a single expression filter.
*
- * @param filter the filter to set
+ * @param filter the expression filter to set
* @return This
*/
- public HeatmapLayer withFilter(Filter.Statement filter) {
+ public HeatmapLayer withFilter(Expression filter) {
setFilter(filter);
return this;
}
/**
+ * Get a single expression filter.
+ *
+ * @return the expression filter to get
+ */
+ @Nullable
+ public Expression getFilter() {
+ Expression expression = null;
+ JsonArray array = (JsonArray) nativeGetFilter();
+ if (array != null) {
+ expression = Expression.Converter.convert(array);
+ }
+ return expression;
+ }
+
+ /**
* Set a property or properties.
*
* @param properties the var-args properties
@@ -168,6 +186,32 @@ public class HeatmapLayer extends Layer {
}
/**
+ * Get the HeatmapColor property
+ *
+ * @return property wrapper value around String
+ */
+ @SuppressWarnings("unchecked")
+ public PropertyValue<String> getHeatmapColor() {
+ return (PropertyValue<String>) new PropertyValue("heatmap-color", nativeGetHeatmapColor());
+ }
+
+ /**
+ * Defines the color of each pixel based on its density value in a heatmap. Should be an expression that uses `["heatmap-density"]` as input.
+ *
+ * @return int representation of a rgba string color
+ * @throws RuntimeException thrown if property isn't a value
+ */
+ @ColorInt
+ public int getHeatmapColorAsInt() {
+ PropertyValue<String> value = getHeatmapColor();
+ if (value.isValue()) {
+ return rgbaToColor(value.getValue());
+ } else {
+ throw new RuntimeException("heatmap-color was set as a Function");
+ }
+ }
+
+ /**
* Get the HeatmapOpacity property
*
* @return property wrapper value around Float
@@ -209,6 +253,8 @@ public class HeatmapLayer extends Layer {
private native void nativeSetHeatmapIntensityTransition(long duration, long delay);
+ private native Object nativeGetHeatmapColor();
+
private native Object nativeGetHeatmapOpacity();
private native TransitionOptions nativeGetHeatmapOpacityTransition();
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/HillshadeLayer.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/HillshadeLayer.java
index 7e3d3a7779..fb086f424b 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/HillshadeLayer.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/HillshadeLayer.java
@@ -4,10 +4,13 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
+import com.google.gson.JsonArray;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
/**
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 5400e04589..411fbe4435 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
@@ -2,8 +2,9 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.NonNull;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
import com.mapbox.mapboxsdk.style.expressions.Expression;
-import com.mapbox.mapboxsdk.style.functions.Function;
/**
* Base class for the different Layer types
@@ -72,6 +73,8 @@ public abstract class Layer {
protected native void nativeSetFilter(Object[] filter);
+ protected native JsonElement nativeGetFilter();
+
protected native void nativeSetSourceLayer(String sourceLayer);
protected native String nativeGetSourceLayer();
@@ -89,12 +92,8 @@ public abstract class Layer {
}
private Object convertValue(Object value) {
- if (value != null) {
- if (value instanceof Function) {
- return ((Function) value).toValueObject();
- } else if (value instanceof Expression) {
- return ((Expression) value).toArray();
- }
+ if (value != null && value instanceof Expression) {
+ return ((Expression) value).toArray();
}
return 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 ca106cc106..5e6e6d38e7 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
@@ -4,10 +4,13 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
+import com.google.gson.JsonArray;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
/**
@@ -69,26 +72,41 @@ public class LineLayer extends Layer {
}
/**
- * Set a single filter.
+ * Set a single expression filter.
*
- * @param filter the filter to set
+ * @param filter the expression filter to set
*/
- public void setFilter(Filter.Statement filter) {
+ public void setFilter(Expression filter) {
nativeSetFilter(filter.toArray());
}
/**
- * Set a single filter.
+ * Set a single expression filter.
*
- * @param filter the filter to set
+ * @param filter the expression filter to set
* @return This
*/
- public LineLayer withFilter(Filter.Statement filter) {
+ public LineLayer withFilter(Expression filter) {
setFilter(filter);
return this;
}
/**
+ * Get a single expression filter.
+ *
+ * @return the expression filter to get
+ */
+ @Nullable
+ public Expression getFilter() {
+ Expression expression = null;
+ JsonArray array = (JsonArray) nativeGetFilter();
+ if (array != null) {
+ expression = Expression.Converter.convert(array);
+ }
+ return expression;
+ }
+
+ /**
* Set a property or properties.
*
* @param properties the var-args properties
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 18ee05e63b..4289deeda3 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
@@ -4,9 +4,7 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.ColorInt;
-import com.mapbox.mapboxsdk.style.functions.CameraFunction;
import com.mapbox.mapboxsdk.style.expressions.Expression;
-import com.mapbox.mapboxsdk.style.functions.Function;
import java.util.Locale;
@@ -28,18 +26,6 @@ public class PropertyFactory {
}
/**
- * Set the property visibility.
- *
- * @param <T> the function input type
- * @param function the visibility function
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, String>> visibility(Function<T, String> function) {
- return new LayoutPropertyValue<>("visibility", function);
- }
-
- /**
* Whether or not the fill should be antialiased.
*
* @param value a Boolean value
@@ -59,19 +45,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-antialias", expression);
}
-
- /**
- * Whether or not the fill should be antialiased.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Boolean
- * @return property wrapper around a Boolean function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Boolean>> fillAntialias(CameraFunction<Z, Boolean> function) {
- return new PaintPropertyValue<>("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.
*
@@ -92,19 +65,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-opacity", expression);
}
-
- /**
- * 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 <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> fillOpacity(Function<T, Float> function) {
- return new PaintPropertyValue<>("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.
*
@@ -135,19 +95,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-color", expression);
}
-
- /**
- * 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 <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, String>> fillColor(Function<T, String> function) {
- return new PaintPropertyValue<>("fill-color", function);
- }
-
/**
* The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified.
*
@@ -178,19 +125,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-outline-color", expression);
}
-
- /**
- * The outline color of the fill. Matches the value of {@link PropertyFactory#fillColor} if unspecified.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, String>> fillOutlineColor(Function<T, String> function) {
- return new PaintPropertyValue<>("fill-outline-color", function);
- }
-
/**
* The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
*
@@ -211,19 +145,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-translate", expression);
}
-
- /**
- * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float[]
- * @return property wrapper around a Float[] function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> fillTranslate(CameraFunction<Z, Float[]> function) {
- return new PaintPropertyValue<>("fill-translate", function);
- }
-
/**
* Controls the frame of reference for {@link PropertyFactory#fillTranslate}.
*
@@ -244,19 +165,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-translate-anchor", expression);
}
-
- /**
- * Controls the frame of reference for {@link PropertyFactory#fillTranslate}.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> fillTranslateAnchor(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("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).
*
@@ -277,19 +185,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-pattern", expression);
}
-
- /**
- * 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 <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> fillPattern(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("fill-pattern", function);
- }
-
/**
* The opacity at which the line will be drawn.
*
@@ -310,19 +205,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-opacity", expression);
}
-
- /**
- * The opacity at which the line will be drawn.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> lineOpacity(Function<T, Float> function) {
- return new PaintPropertyValue<>("line-opacity", function);
- }
-
/**
* The color with which the line will be drawn.
*
@@ -353,19 +235,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-color", expression);
}
-
- /**
- * The color with which the line will be drawn.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, String>> lineColor(Function<T, String> function) {
- return new PaintPropertyValue<>("line-color", function);
- }
-
/**
* The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
*
@@ -386,19 +255,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-translate", expression);
}
-
- /**
- * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float[]
- * @return property wrapper around a Float[] function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> lineTranslate(CameraFunction<Z, Float[]> function) {
- return new PaintPropertyValue<>("line-translate", function);
- }
-
/**
* Controls the frame of reference for {@link PropertyFactory#lineTranslate}.
*
@@ -419,19 +275,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-translate-anchor", expression);
}
-
- /**
- * Controls the frame of reference for {@link PropertyFactory#lineTranslate}.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> lineTranslateAnchor(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("line-translate-anchor", function);
- }
-
/**
* Stroke thickness.
*
@@ -452,19 +295,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-width", expression);
}
-
- /**
- * Stroke thickness.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> lineWidth(Function<T, Float> function) {
- return new PaintPropertyValue<>("line-width", function);
- }
-
/**
* Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.
*
@@ -485,19 +315,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-gap-width", expression);
}
-
- /**
- * Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> lineGapWidth(Function<T, Float> function) {
- return new PaintPropertyValue<>("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.
*
@@ -518,19 +335,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-offset", expression);
}
-
- /**
- * 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 <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> lineOffset(Function<T, Float> function) {
- return new PaintPropertyValue<>("line-offset", function);
- }
-
/**
* Blur applied to the line, in density-independent pixels.
*
@@ -551,19 +355,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-blur", expression);
}
-
- /**
- * Blur applied to the line, in density-independent pixels.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> lineBlur(Function<T, Float> function) {
- return new PaintPropertyValue<>("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 density-independent pixels, multiply the length by the current line width.
*
@@ -584,19 +375,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-dasharray", expression);
}
-
- /**
- * 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 density-independent pixels, multiply the length by the current line width.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float[]
- * @return property wrapper around a Float[] function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> lineDasharray(CameraFunction<Z, Float[]> function) {
- return new PaintPropertyValue<>("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).
*
@@ -617,19 +395,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("line-pattern", expression);
}
-
- /**
- * 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 <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> linePattern(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("line-pattern", function);
- }
-
/**
* The opacity at which the icon will be drawn.
*
@@ -650,19 +415,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("icon-opacity", expression);
}
-
- /**
- * The opacity at which the icon will be drawn.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> iconOpacity(Function<T, Float> function) {
- return new PaintPropertyValue<>("icon-opacity", function);
- }
-
/**
* The color of the icon. This can only be used with sdf icons.
*
@@ -693,19 +445,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("icon-color", expression);
}
-
- /**
- * The color of the icon. This can only be used with sdf icons.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, String>> iconColor(Function<T, String> function) {
- return new PaintPropertyValue<>("icon-color", function);
- }
-
/**
* The color of the icon's halo. Icon halos can only be used with SDF icons.
*
@@ -736,19 +475,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("icon-halo-color", expression);
}
-
- /**
- * The color of the icon's halo. Icon halos can only be used with SDF icons.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, String>> iconHaloColor(Function<T, String> function) {
- return new PaintPropertyValue<>("icon-halo-color", function);
- }
-
/**
* Distance of halo to the icon outline.
*
@@ -769,19 +495,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("icon-halo-width", expression);
}
-
- /**
- * Distance of halo to the icon outline.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> iconHaloWidth(Function<T, Float> function) {
- return new PaintPropertyValue<>("icon-halo-width", function);
- }
-
/**
* Fade out the halo towards the outside.
*
@@ -802,19 +515,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("icon-halo-blur", expression);
}
-
- /**
- * Fade out the halo towards the outside.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> iconHaloBlur(Function<T, Float> function) {
- return new PaintPropertyValue<>("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.
*
@@ -835,19 +535,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("icon-translate", expression);
}
-
- /**
- * 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 <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float[]
- * @return property wrapper around a Float[] function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> iconTranslate(CameraFunction<Z, Float[]> function) {
- return new PaintPropertyValue<>("icon-translate", function);
- }
-
/**
* Controls the frame of reference for {@link PropertyFactory#iconTranslate}.
*
@@ -868,19 +555,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("icon-translate-anchor", expression);
}
-
- /**
- * Controls the frame of reference for {@link PropertyFactory#iconTranslate}.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> iconTranslateAnchor(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("icon-translate-anchor", function);
- }
-
/**
* The opacity at which the text will be drawn.
*
@@ -901,19 +575,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("text-opacity", expression);
}
-
- /**
- * The opacity at which the text will be drawn.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> textOpacity(Function<T, Float> function) {
- return new PaintPropertyValue<>("text-opacity", function);
- }
-
/**
* The color with which the text will be drawn.
*
@@ -944,19 +605,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("text-color", expression);
}
-
- /**
- * The color with which the text will be drawn.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, String>> textColor(Function<T, String> function) {
- return new PaintPropertyValue<>("text-color", function);
- }
-
/**
* The color of the text's halo, which helps it stand out from backgrounds.
*
@@ -987,19 +635,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("text-halo-color", expression);
}
-
- /**
- * The color of the text's halo, which helps it stand out from backgrounds.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, String>> textHaloColor(Function<T, String> function) {
- return new PaintPropertyValue<>("text-halo-color", function);
- }
-
/**
* Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.
*
@@ -1020,19 +655,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("text-halo-width", expression);
}
-
- /**
- * Distance of halo to the font outline. Max text halo width is 1/4 of the font-size.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> textHaloWidth(Function<T, Float> function) {
- return new PaintPropertyValue<>("text-halo-width", function);
- }
-
/**
* The halo's fadeout distance towards the outside.
*
@@ -1053,19 +675,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("text-halo-blur", expression);
}
-
- /**
- * The halo's fadeout distance towards the outside.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> textHaloBlur(Function<T, Float> function) {
- return new PaintPropertyValue<>("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.
*
@@ -1086,19 +695,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("text-translate", expression);
}
-
- /**
- * 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 <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float[]
- * @return property wrapper around a Float[] function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> textTranslate(CameraFunction<Z, Float[]> function) {
- return new PaintPropertyValue<>("text-translate", function);
- }
-
/**
* Controls the frame of reference for {@link PropertyFactory#textTranslate}.
*
@@ -1119,19 +715,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("text-translate-anchor", expression);
}
-
- /**
- * Controls the frame of reference for {@link PropertyFactory#textTranslate}.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> textTranslateAnchor(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("text-translate-anchor", function);
- }
-
/**
* Circle radius.
*
@@ -1152,19 +735,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-radius", expression);
}
-
- /**
- * Circle radius.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> circleRadius(Function<T, Float> function) {
- return new PaintPropertyValue<>("circle-radius", function);
- }
-
/**
* The fill color of the circle.
*
@@ -1195,19 +765,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-color", expression);
}
-
- /**
- * The fill color of the circle.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, String>> circleColor(Function<T, String> function) {
- return new PaintPropertyValue<>("circle-color", function);
- }
-
/**
* Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity.
*
@@ -1228,19 +785,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-blur", expression);
}
-
- /**
- * Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> circleBlur(Function<T, Float> function) {
- return new PaintPropertyValue<>("circle-blur", function);
- }
-
/**
* The opacity at which the circle will be drawn.
*
@@ -1261,19 +805,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-opacity", expression);
}
-
- /**
- * The opacity at which the circle will be drawn.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> circleOpacity(Function<T, Float> function) {
- return new PaintPropertyValue<>("circle-opacity", function);
- }
-
/**
* The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
*
@@ -1294,19 +825,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-translate", expression);
}
-
- /**
- * The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float[]
- * @return property wrapper around a Float[] function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> circleTranslate(CameraFunction<Z, Float[]> function) {
- return new PaintPropertyValue<>("circle-translate", function);
- }
-
/**
* Controls the frame of reference for {@link PropertyFactory#circleTranslate}.
*
@@ -1327,19 +845,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-translate-anchor", expression);
}
-
- /**
- * Controls the frame of reference for {@link PropertyFactory#circleTranslate}.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> circleTranslateAnchor(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("circle-translate-anchor", function);
- }
-
/**
* Controls the scaling behavior of the circle when the map is pitched.
*
@@ -1360,19 +865,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-pitch-scale", expression);
}
-
- /**
- * Controls the scaling behavior of the circle when the map is pitched.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> circlePitchScale(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("circle-pitch-scale", function);
- }
-
/**
* Orientation of circle when map is pitched.
*
@@ -1393,19 +885,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-pitch-alignment", expression);
}
-
- /**
- * Orientation of circle when map is pitched.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> circlePitchAlignment(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("circle-pitch-alignment", function);
- }
-
/**
* The width of the circle's stroke. Strokes are placed outside of the {@link PropertyFactory#circleRadius}.
*
@@ -1426,19 +905,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-stroke-width", expression);
}
-
- /**
- * The width of the circle's stroke. Strokes are placed outside of the {@link PropertyFactory#circleRadius}.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> circleStrokeWidth(Function<T, Float> function) {
- return new PaintPropertyValue<>("circle-stroke-width", function);
- }
-
/**
* The stroke color of the circle.
*
@@ -1469,19 +935,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-stroke-color", expression);
}
-
- /**
- * The stroke color of the circle.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, String>> circleStrokeColor(Function<T, String> function) {
- return new PaintPropertyValue<>("circle-stroke-color", function);
- }
-
/**
* The opacity of the circle's stroke.
*
@@ -1502,19 +955,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("circle-stroke-opacity", expression);
}
-
- /**
- * The opacity of the circle's stroke.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> circleStrokeOpacity(Function<T, Float> function) {
- return new PaintPropertyValue<>("circle-stroke-opacity", function);
- }
-
/**
* Radius of influence of one heatmap point in density-independent pixels. Increasing the value makes the heatmap smoother, but less detailed.
*
@@ -1535,19 +975,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("heatmap-radius", expression);
}
-
- /**
- * Radius of influence of one heatmap point in density-independent pixels. Increasing the value makes the heatmap smoother, but less detailed.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> heatmapRadius(Function<T, Float> function) {
- return new PaintPropertyValue<>("heatmap-radius", function);
- }
-
/**
* A measure of how much an individual point contributes to the heatmap. A value of 10 would be equivalent to having 10 points of weight 1 in the same spot. Especially useful when combined with clustering.
*
@@ -1568,19 +995,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("heatmap-weight", expression);
}
-
- /**
- * A measure of how much an individual point contributes to the heatmap. A value of 10 would be equivalent to having 10 points of weight 1 in the same spot. Especially useful when combined with clustering.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> heatmapWeight(Function<T, Float> function) {
- return new PaintPropertyValue<>("heatmap-weight", function);
- }
-
/**
* Similar to {@link PropertyFactory#heatmapWeight} but controls the intensity of the heatmap globally. Primarily used for adjusting the heatmap based on zoom level.
*
@@ -1601,17 +1015,34 @@ public class PropertyFactory {
return new PaintPropertyValue<>("heatmap-intensity", expression);
}
+ /**
+ * Defines the color of each pixel based on its density value in a heatmap. Should be an expression that uses `["heatmap-density"]` as input.
+ *
+ * @param value a int color value
+ * @return property wrapper around String color
+ */
+ public static PropertyValue<String> heatmapColor(@ColorInt int value) {
+ return new PaintPropertyValue<>("heatmap-color", colorToRgbaString(value));
+ }
/**
- * Similar to {@link PropertyFactory#heatmapWeight} but controls the intensity of the heatmap globally. Primarily used for adjusting the heatmap based on zoom level.
+ * Defines the color of each pixel based on its density value in a heatmap. Should be an expression that uses `["heatmap-density"]` as input.
+ *
+ * @param value a String value
+ * @return property wrapper around String
+ */
+ public static PropertyValue<String> heatmapColor(String value) {
+ return new PaintPropertyValue<>("heatmap-color", value);
+ }
+
+ /**
+ * Defines the color of each pixel based on its density value in a heatmap. Should be an expression that uses `["heatmap-density"]` as input.
*
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
+ * @param expression an expression statement
+ * @return property wrapper around an expression statement
*/
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> heatmapIntensity(CameraFunction<Z, Float> function) {
- return new PaintPropertyValue<>("heatmap-intensity", function);
+ public static PropertyValue<Expression> heatmapColor(Expression expression) {
+ return new PaintPropertyValue<>("heatmap-color", expression);
}
/**
@@ -1634,19 +1065,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("heatmap-opacity", expression);
}
-
- /**
- * The global opacity at which the heatmap layer will be drawn.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> heatmapOpacity(CameraFunction<Z, Float> function) {
- return new PaintPropertyValue<>("heatmap-opacity", function);
- }
-
/**
* The opacity of the entire fill extrusion layer. This is rendered on a per-layer, not per-feature, basis, and data-driven styling is not available.
*
@@ -1667,19 +1085,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-extrusion-opacity", expression);
}
-
- /**
- * The opacity of the entire fill extrusion layer. This is rendered on a per-layer, not per-feature, basis, and data-driven styling is not available.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> fillExtrusionOpacity(CameraFunction<Z, Float> function) {
- return new PaintPropertyValue<>("fill-extrusion-opacity", function);
- }
-
/**
* The base color of the extruded fill. The extrusion's surfaces will be shaded differently based on this color in combination with the root `light` settings. If this color is specified as `rgba` with an alpha component, the alpha component will be ignored; use {@link PropertyFactory#fillExtrusionOpacity} to set layer opacity.
*
@@ -1710,19 +1115,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-extrusion-color", expression);
}
-
- /**
- * The base color of the extruded fill. The extrusion's surfaces will be shaded differently based on this color in combination with the root `light` settings. If this color is specified as `rgba` with an alpha component, the alpha component will be ignored; use {@link PropertyFactory#fillExtrusionOpacity} to set layer opacity.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, String>> fillExtrusionColor(Function<T, String> function) {
- return new PaintPropertyValue<>("fill-extrusion-color", function);
- }
-
/**
* The geometry's offset. Values are [x, y] where negatives indicate left and up (on the flat plane), respectively.
*
@@ -1743,19 +1135,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-extrusion-translate", expression);
}
-
- /**
- * The geometry's offset. Values are [x, y] where negatives indicate left and up (on the flat plane), respectively.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float[]
- * @return property wrapper around a Float[] function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> fillExtrusionTranslate(CameraFunction<Z, Float[]> function) {
- return new PaintPropertyValue<>("fill-extrusion-translate", function);
- }
-
/**
* Controls the frame of reference for {@link PropertyFactory#fillExtrusionTranslate}.
*
@@ -1776,19 +1155,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-extrusion-translate-anchor", expression);
}
-
- /**
- * Controls the frame of reference for {@link PropertyFactory#fillExtrusionTranslate}.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> fillExtrusionTranslateAnchor(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("fill-extrusion-translate-anchor", function);
- }
-
/**
* Name of image in sprite to use for drawing images on extruded fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
*
@@ -1809,19 +1175,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-extrusion-pattern", expression);
}
-
- /**
- * Name of image in sprite to use for drawing images on extruded fills. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> fillExtrusionPattern(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("fill-extrusion-pattern", function);
- }
-
/**
* The height with which to extrude this layer.
*
@@ -1842,19 +1195,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-extrusion-height", expression);
}
-
- /**
- * The height with which to extrude this layer.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> fillExtrusionHeight(Function<T, Float> function) {
- return new PaintPropertyValue<>("fill-extrusion-height", function);
- }
-
/**
* The height with which to extrude the base of this layer. Must be less than or equal to {@link PropertyFactory#fillExtrusionHeight}.
*
@@ -1875,19 +1215,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("fill-extrusion-base", expression);
}
-
- /**
- * The height with which to extrude the base of this layer. Must be less than or equal to {@link PropertyFactory#fillExtrusionHeight}.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, Float>> fillExtrusionBase(Function<T, Float> function) {
- return new PaintPropertyValue<>("fill-extrusion-base", function);
- }
-
/**
* The opacity at which the image will be drawn.
*
@@ -1908,19 +1235,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("raster-opacity", expression);
}
-
- /**
- * The opacity at which the image will be drawn.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> rasterOpacity(CameraFunction<Z, Float> function) {
- return new PaintPropertyValue<>("raster-opacity", function);
- }
-
/**
* Rotates hues around the color wheel.
*
@@ -1941,19 +1255,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("raster-hue-rotate", expression);
}
-
- /**
- * Rotates hues around the color wheel.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> rasterHueRotate(CameraFunction<Z, Float> function) {
- return new PaintPropertyValue<>("raster-hue-rotate", function);
- }
-
/**
* Increase or reduce the brightness of the image. The value is the minimum brightness.
*
@@ -1974,19 +1275,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("raster-brightness-min", expression);
}
-
- /**
- * Increase or reduce the brightness of the image. The value is the minimum brightness.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> rasterBrightnessMin(CameraFunction<Z, Float> function) {
- return new PaintPropertyValue<>("raster-brightness-min", function);
- }
-
/**
* Increase or reduce the brightness of the image. The value is the maximum brightness.
*
@@ -2007,19 +1295,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("raster-brightness-max", expression);
}
-
- /**
- * Increase or reduce the brightness of the image. The value is the maximum brightness.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> rasterBrightnessMax(CameraFunction<Z, Float> function) {
- return new PaintPropertyValue<>("raster-brightness-max", function);
- }
-
/**
* Increase or reduce the saturation of the image.
*
@@ -2040,19 +1315,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("raster-saturation", expression);
}
-
- /**
- * Increase or reduce the saturation of the image.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> rasterSaturation(CameraFunction<Z, Float> function) {
- return new PaintPropertyValue<>("raster-saturation", function);
- }
-
/**
* Increase or reduce the contrast of the image.
*
@@ -2073,19 +1335,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("raster-contrast", expression);
}
-
- /**
- * Increase or reduce the contrast of the image.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> rasterContrast(CameraFunction<Z, Float> function) {
- return new PaintPropertyValue<>("raster-contrast", function);
- }
-
/**
* Fade duration when a new tile is added.
*
@@ -2106,19 +1355,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("raster-fade-duration", expression);
}
-
- /**
- * Fade duration when a new tile is added.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> rasterFadeDuration(CameraFunction<Z, Float> function) {
- return new PaintPropertyValue<>("raster-fade-duration", function);
- }
-
/**
* The direction of the light source used to generate the hillshading with 0 as the top of the viewport if {@link Property.HILLSHADE_ILLUMINATION_ANCHOR} is set to `viewport` and due north if {@link Property.HILLSHADE_ILLUMINATION_ANCHOR} is set to `map`.
*
@@ -2139,19 +1375,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("hillshade-illumination-direction", expression);
}
-
- /**
- * The direction of the light source used to generate the hillshading with 0 as the top of the viewport if {@link Property.HILLSHADE_ILLUMINATION_ANCHOR} is set to `viewport` and due north if {@link Property.HILLSHADE_ILLUMINATION_ANCHOR} is set to `map`.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> hillshadeIlluminationDirection(CameraFunction<Z, Float> function) {
- return new PaintPropertyValue<>("hillshade-illumination-direction", function);
- }
-
/**
* Direction of light source when map is rotated.
*
@@ -2172,19 +1395,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("hillshade-illumination-anchor", expression);
}
-
- /**
- * Direction of light source when map is rotated.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> hillshadeIlluminationAnchor(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("hillshade-illumination-anchor", function);
- }
-
/**
* Intensity of the hillshade
*
@@ -2205,19 +1415,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("hillshade-exaggeration", expression);
}
-
- /**
- * Intensity of the hillshade
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> hillshadeExaggeration(CameraFunction<Z, Float> function) {
- return new PaintPropertyValue<>("hillshade-exaggeration", function);
- }
-
/**
* The shading color of areas that face away from the light source.
*
@@ -2248,19 +1445,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("hillshade-shadow-color", expression);
}
-
- /**
- * The shading color of areas that face away from the light source.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> hillshadeShadowColor(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("hillshade-shadow-color", function);
- }
-
/**
* The shading color of areas that faces towards the light source.
*
@@ -2291,19 +1475,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("hillshade-highlight-color", expression);
}
-
- /**
- * The shading color of areas that faces towards the light source.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> hillshadeHighlightColor(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("hillshade-highlight-color", function);
- }
-
/**
* The shading color used to accentuate rugged terrain like sharp cliffs and gorges.
*
@@ -2334,19 +1505,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("hillshade-accent-color", expression);
}
-
- /**
- * The shading color used to accentuate rugged terrain like sharp cliffs and gorges.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> hillshadeAccentColor(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("hillshade-accent-color", function);
- }
-
/**
* The color with which the background will be drawn.
*
@@ -2377,19 +1535,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("background-color", expression);
}
-
- /**
- * The color with which the background will be drawn.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> backgroundColor(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("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).
*
@@ -2410,19 +1555,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("background-pattern", expression);
}
-
- /**
- * 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 <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> backgroundPattern(CameraFunction<Z, String> function) {
- return new PaintPropertyValue<>("background-pattern", function);
- }
-
/**
* The opacity at which the background will be drawn.
*
@@ -2443,19 +1575,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("background-opacity", expression);
}
-
- /**
- * The opacity at which the background will be drawn.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> backgroundOpacity(CameraFunction<Z, Float> function) {
- return new PaintPropertyValue<>("background-opacity", function);
- }
-
/**
* The display of line endings.
*
@@ -2476,18 +1595,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("line-cap", value);
}
-
- /**
- * The display of line endings.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> lineCap(CameraFunction<Z, String> function) {
- return new LayoutPropertyValue<>("line-cap", function);
- }
-
/**
* The display of lines when joining.
*
@@ -2508,18 +1615,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("line-join", value);
}
-
- /**
- * The display of lines when joining.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static <T> PropertyValue<Function<T, String>> lineJoin(Function<T, String> function) {
- return new LayoutPropertyValue<>("line-join", function);
- }
-
/**
* Used to automatically convert miter joins to bevel joins for sharp angles.
*
@@ -2540,18 +1635,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("line-miter-limit", value);
}
-
- /**
- * Used to automatically convert miter joins to bevel joins for sharp angles.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> lineMiterLimit(CameraFunction<Z, Float> function) {
- return new LayoutPropertyValue<>("line-miter-limit", function);
- }
-
/**
* Used to automatically convert round joins to miter joins for shallow angles.
*
@@ -2572,18 +1655,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("line-round-limit", value);
}
-
- /**
- * Used to automatically convert round joins to miter joins for shallow angles.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> lineRoundLimit(CameraFunction<Z, Float> function) {
- return new LayoutPropertyValue<>("line-round-limit", function);
- }
-
/**
* Label placement relative to its geometry.
*
@@ -2604,18 +1675,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("symbol-placement", value);
}
-
- /**
- * Label placement relative to its geometry.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> symbolPlacement(CameraFunction<Z, String> function) {
- return new LayoutPropertyValue<>("symbol-placement", function);
- }
-
/**
* Distance between two symbol anchors.
*
@@ -2636,18 +1695,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("symbol-spacing", value);
}
-
- /**
- * Distance between two symbol anchors.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> symbolSpacing(CameraFunction<Z, Float> function) {
- return new LayoutPropertyValue<>("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.
*
@@ -2668,18 +1715,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("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 <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Boolean
- * @return property wrapper around a Boolean function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Boolean>> symbolAvoidEdges(CameraFunction<Z, Boolean> function) {
- return new LayoutPropertyValue<>("symbol-avoid-edges", function);
- }
-
/**
* If true, the icon will be visible even if it collides with other previously drawn symbols.
*
@@ -2700,18 +1735,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-allow-overlap", value);
}
-
- /**
- * If true, the icon will be visible even if it collides with other previously drawn symbols.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Boolean
- * @return property wrapper around a Boolean function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Boolean>> iconAllowOverlap(CameraFunction<Z, Boolean> function) {
- return new LayoutPropertyValue<>("icon-allow-overlap", function);
- }
-
/**
* If true, other symbols can be visible even if they collide with the icon.
*
@@ -2732,18 +1755,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-ignore-placement", value);
}
-
- /**
- * If true, other symbols can be visible even if they collide with the icon.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Boolean
- * @return property wrapper around a Boolean function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Boolean>> iconIgnorePlacement(CameraFunction<Z, Boolean> function) {
- return new LayoutPropertyValue<>("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.
*
@@ -2764,18 +1775,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("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 <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Boolean
- * @return property wrapper around a Boolean function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Boolean>> iconOptional(CameraFunction<Z, Boolean> function) {
- return new LayoutPropertyValue<>("icon-optional", function);
- }
-
/**
* In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of icons.
*
@@ -2796,18 +1795,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-rotation-alignment", value);
}
-
- /**
- * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of icons.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> iconRotationAlignment(CameraFunction<Z, String> function) {
- return new LayoutPropertyValue<>("icon-rotation-alignment", function);
- }
-
/**
* Scales the original size of the icon by the provided factor. The new pixel size of the image will be the original pixel size multiplied by {@link PropertyFactory#iconSize}. 1 is the original size; 3 triples the size of the image.
*
@@ -2828,18 +1815,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-size", value);
}
-
- /**
- * Scales the original size of the icon by the provided factor. The new pixel size of the image will be the original pixel size multiplied by {@link PropertyFactory#iconSize}. 1 is the original size; 3 triples the size of the image.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static <T> PropertyValue<Function<T, Float>> iconSize(Function<T, Float> function) {
- return new LayoutPropertyValue<>("icon-size", function);
- }
-
/**
* Scales the icon to fit around the associated text.
*
@@ -2860,18 +1835,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-text-fit", value);
}
-
- /**
- * Scales the icon to fit around the associated text.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> iconTextFit(CameraFunction<Z, String> function) {
- return new LayoutPropertyValue<>("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.
*
@@ -2892,20 +1855,8 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("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 <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float[]
- * @return property wrapper around a Float[] function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float[]>> iconTextFitPadding(CameraFunction<Z, Float[]> function) {
- return new LayoutPropertyValue<>("icon-text-fit-padding", function);
- }
-
- /**
- * Name of image in sprite to use for drawing an image background. Within literal values and zoom functions, property names enclosed in curly brackets (e.g. `{token}`) are replaced with the value of the named property. Expressions and property functions do not support this syntax; for equivalent functionality in expressions, use the [`concat`](#expressions-concat) and [`get`](#expressions-get) operators.
+ * Name of image in sprite to use for drawing an image background.
*
* @param value a String value
* @return property wrapper around String
@@ -2915,7 +1866,7 @@ public class PropertyFactory {
}
/**
- * Name of image in sprite to use for drawing an image background. Within literal values and zoom functions, property names enclosed in curly brackets (e.g. `{token}`) are replaced with the value of the named property. Expressions and property functions do not support this syntax; for equivalent functionality in expressions, use the [`concat`](#expressions-concat) and [`get`](#expressions-get) operators.
+ * Name of image in sprite to use for drawing an image background.
*
* @param value a String value
* @return property wrapper around String
@@ -2924,18 +1875,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-image", value);
}
-
- /**
- * Name of image in sprite to use for drawing an image background. Within literal values and zoom functions, property names enclosed in curly brackets (e.g. `{token}`) are replaced with the value of the named property. Expressions and property functions do not support this syntax; for equivalent functionality in expressions, use the [`concat`](#expressions-concat) and [`get`](#expressions-get) operators.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static <T> PropertyValue<Function<T, String>> iconImage(Function<T, String> function) {
- return new LayoutPropertyValue<>("icon-image", function);
- }
-
/**
* Rotates the icon clockwise.
*
@@ -2956,18 +1895,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-rotate", value);
}
-
- /**
- * Rotates the icon clockwise.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static <T> PropertyValue<Function<T, Float>> iconRotate(Function<T, Float> function) {
- return new LayoutPropertyValue<>("icon-rotate", function);
- }
-
/**
* Size of the additional area around the icon bounding box used for detecting symbol collisions.
*
@@ -2988,18 +1915,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-padding", value);
}
-
- /**
- * Size of the additional area around the icon bounding box used for detecting symbol collisions.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> iconPadding(CameraFunction<Z, Float> function) {
- return new LayoutPropertyValue<>("icon-padding", function);
- }
-
/**
* If true, the icon may be flipped to prevent it from being rendered upside-down.
*
@@ -3020,18 +1935,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-keep-upright", value);
}
-
- /**
- * If true, the icon may be flipped to prevent it from being rendered upside-down.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Boolean
- * @return property wrapper around a Boolean function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Boolean>> iconKeepUpright(CameraFunction<Z, Boolean> function) {
- return new LayoutPropertyValue<>("icon-keep-upright", function);
- }
-
/**
* Offset distance of icon from its anchor. Positive values indicate right and down, while negative values indicate left and up. Each component is multiplied by the value of {@link PropertyFactory#iconSize} to obtain the final offset in density-independent pixels. When combined with {@link PropertyFactory#iconRotate} the offset will be as if the rotated direction was up.
*
@@ -3052,18 +1955,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-offset", value);
}
-
- /**
- * Offset distance of icon from its anchor. Positive values indicate right and down, while negative values indicate left and up. Each component is multiplied by the value of {@link PropertyFactory#iconSize} to obtain the final offset in density-independent pixels. When combined with {@link PropertyFactory#iconRotate} the offset will be as if the rotated direction was up.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float[]
- * @return property wrapper around a Float[] function
- */
- public static <T> PropertyValue<Function<T, Float[]>> iconOffset(Function<T, Float[]> function) {
- return new LayoutPropertyValue<>("icon-offset", function);
- }
-
/**
* Part of the icon placed closest to the anchor.
*
@@ -3084,18 +1975,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-anchor", value);
}
-
- /**
- * Part of the icon placed closest to the anchor.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static <T> PropertyValue<Function<T, String>> iconAnchor(Function<T, String> function) {
- return new LayoutPropertyValue<>("icon-anchor", function);
- }
-
/**
* Orientation of icon when map is pitched.
*
@@ -3116,18 +1995,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("icon-pitch-alignment", value);
}
-
- /**
- * Orientation of icon when map is pitched.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> iconPitchAlignment(CameraFunction<Z, String> function) {
- return new LayoutPropertyValue<>("icon-pitch-alignment", function);
- }
-
/**
* Orientation of text when map is pitched.
*
@@ -3148,18 +2015,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-pitch-alignment", value);
}
-
- /**
- * Orientation of text when map is pitched.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> textPitchAlignment(CameraFunction<Z, String> function) {
- return new LayoutPropertyValue<>("text-pitch-alignment", function);
- }
-
/**
* In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of the individual glyphs forming the text.
*
@@ -3180,20 +2035,8 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-rotation-alignment", value);
}
-
- /**
- * In combination with {@link Property.SYMBOL_PLACEMENT}, determines the rotation behavior of the individual glyphs forming the text.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for String
- * @return property wrapper around a String function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, String>> textRotationAlignment(CameraFunction<Z, String> function) {
- return new LayoutPropertyValue<>("text-rotation-alignment", function);
- }
-
/**
- * Value to use for a text label. Within literal values and zoom functions, property names enclosed in curly brackets (e.g. `{token}`) are replaced with the value of the named property. Expressions and property functions do not support this syntax; for equivalent functionality in expressions, use the [`concat`](#expressions-concat) and [`get`](#expressions-get) operators.
+ * Value to use for a text label.
*
* @param value a String value
* @return property wrapper around String
@@ -3203,7 +2046,7 @@ public class PropertyFactory {
}
/**
- * Value to use for a text label. Within literal values and zoom functions, property names enclosed in curly brackets (e.g. `{token}`) are replaced with the value of the named property. Expressions and property functions do not support this syntax; for equivalent functionality in expressions, use the [`concat`](#expressions-concat) and [`get`](#expressions-get) operators.
+ * Value to use for a text label.
*
* @param value a String value
* @return property wrapper around String
@@ -3212,18 +2055,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-field", value);
}
-
- /**
- * Value to use for a text label. Within literal values and zoom functions, property names enclosed in curly brackets (e.g. `{token}`) are replaced with the value of the named property. Expressions and property functions do not support this syntax; for equivalent functionality in expressions, use the [`concat`](#expressions-concat) and [`get`](#expressions-get) operators.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static <T> PropertyValue<Function<T, String>> textField(Function<T, String> function) {
- return new LayoutPropertyValue<>("text-field", function);
- }
-
/**
* Font stack to use for displaying text.
*
@@ -3244,18 +2075,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-font", value);
}
-
- /**
- * Font stack to use for displaying text.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String[]
- * @return property wrapper around a String[] function
- */
- public static <T> PropertyValue<Function<T, String[]>> textFont(Function<T, String[]> function) {
- return new LayoutPropertyValue<>("text-font", function);
- }
-
/**
* Font size.
*
@@ -3276,18 +2095,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-size", value);
}
-
- /**
- * Font size.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static <T> PropertyValue<Function<T, Float>> textSize(Function<T, Float> function) {
- return new LayoutPropertyValue<>("text-size", function);
- }
-
/**
* The maximum line width for text wrapping.
*
@@ -3308,18 +2115,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-max-width", value);
}
-
- /**
- * The maximum line width for text wrapping.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static <T> PropertyValue<Function<T, Float>> textMaxWidth(Function<T, Float> function) {
- return new LayoutPropertyValue<>("text-max-width", function);
- }
-
/**
* Text leading value for multi-line text.
*
@@ -3340,18 +2135,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-line-height", value);
}
-
- /**
- * Text leading value for multi-line text.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> textLineHeight(CameraFunction<Z, Float> function) {
- return new LayoutPropertyValue<>("text-line-height", function);
- }
-
/**
* Text tracking amount.
*
@@ -3372,18 +2155,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-letter-spacing", value);
}
-
- /**
- * Text tracking amount.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static <T> PropertyValue<Function<T, Float>> textLetterSpacing(Function<T, Float> function) {
- return new LayoutPropertyValue<>("text-letter-spacing", function);
- }
-
/**
* Text justification options.
*
@@ -3404,18 +2175,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-justify", value);
}
-
- /**
- * Text justification options.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static <T> PropertyValue<Function<T, String>> textJustify(Function<T, String> function) {
- return new LayoutPropertyValue<>("text-justify", function);
- }
-
/**
* Part of the text placed closest to the anchor.
*
@@ -3436,18 +2195,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-anchor", value);
}
-
- /**
- * Part of the text placed closest to the anchor.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static <T> PropertyValue<Function<T, String>> textAnchor(Function<T, String> function) {
- return new LayoutPropertyValue<>("text-anchor", function);
- }
-
/**
* Maximum angle change between adjacent characters.
*
@@ -3468,18 +2215,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-max-angle", value);
}
-
- /**
- * Maximum angle change between adjacent characters.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> textMaxAngle(CameraFunction<Z, Float> function) {
- return new LayoutPropertyValue<>("text-max-angle", function);
- }
-
/**
* Rotates the text clockwise.
*
@@ -3500,18 +2235,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-rotate", value);
}
-
- /**
- * Rotates the text clockwise.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float
- * @return property wrapper around a Float function
- */
- public static <T> PropertyValue<Function<T, Float>> textRotate(Function<T, Float> function) {
- return new LayoutPropertyValue<>("text-rotate", function);
- }
-
/**
* Size of the additional area around the text bounding box used for detecting symbol collisions.
*
@@ -3532,18 +2255,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-padding", value);
}
-
- /**
- * Size of the additional area around the text bounding box used for detecting symbol collisions.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Float
- * @return property wrapper around a Float function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Float>> textPadding(CameraFunction<Z, Float> function) {
- return new LayoutPropertyValue<>("text-padding", function);
- }
-
/**
* If true, the text may be flipped vertically to prevent it from being rendered upside-down.
*
@@ -3564,18 +2275,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-keep-upright", value);
}
-
- /**
- * If true, the text may be flipped vertically to prevent it from being rendered upside-down.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Boolean
- * @return property wrapper around a Boolean function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Boolean>> textKeepUpright(CameraFunction<Z, Boolean> function) {
- return new LayoutPropertyValue<>("text-keep-upright", function);
- }
-
/**
* Specifies how to capitalize text, similar to the CSS {@link PropertyFactory#textTransform} property.
*
@@ -3596,18 +2295,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-transform", value);
}
-
- /**
- * Specifies how to capitalize text, similar to the CSS {@link PropertyFactory#textTransform} property.
- *
- * @param <T> the function input type
- * @param function a wrapper function for String
- * @return property wrapper around a String function
- */
- public static <T> PropertyValue<Function<T, String>> textTransform(Function<T, String> function) {
- return new LayoutPropertyValue<>("text-transform", function);
- }
-
/**
* Offset distance of text from its anchor. Positive values indicate right and down, while negative values indicate left and up.
*
@@ -3628,18 +2315,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-offset", value);
}
-
- /**
- * Offset distance of text from its anchor. Positive values indicate right and down, while negative values indicate left and up.
- *
- * @param <T> the function input type
- * @param function a wrapper function for Float[]
- * @return property wrapper around a Float[] function
- */
- public static <T> PropertyValue<Function<T, Float[]>> textOffset(Function<T, Float[]> function) {
- return new LayoutPropertyValue<>("text-offset", function);
- }
-
/**
* If true, the text will be visible even if it collides with other previously drawn symbols.
*
@@ -3660,18 +2335,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-allow-overlap", value);
}
-
- /**
- * If true, the text will be visible even if it collides with other previously drawn symbols.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Boolean
- * @return property wrapper around a Boolean function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Boolean>> textAllowOverlap(CameraFunction<Z, Boolean> function) {
- return new LayoutPropertyValue<>("text-allow-overlap", function);
- }
-
/**
* If true, other symbols can be visible even if they collide with the text.
*
@@ -3692,18 +2355,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("text-ignore-placement", value);
}
-
- /**
- * If true, other symbols can be visible even if they collide with the text.
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Boolean
- * @return property wrapper around a Boolean function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Boolean>> textIgnorePlacement(CameraFunction<Z, Boolean> function) {
- return new LayoutPropertyValue<>("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.
*
@@ -3724,18 +2375,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("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 <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for Boolean
- * @return property wrapper around a Boolean function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, Boolean>> textOptional(CameraFunction<Z, Boolean> function) {
- return new LayoutPropertyValue<>("text-optional", function);
- }
-
public static String colorToRgbaString(@ColorInt int value) {
return String.format(Locale.US,"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 a57c440df4..fa1779a6c7 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
@@ -4,8 +4,9 @@ import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
+import com.google.gson.JsonArray;
import com.mapbox.mapboxsdk.exceptions.ConversionException;
-import com.mapbox.mapboxsdk.style.functions.Function;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.utils.ColorUtils;
import timber.log.Timber;
@@ -40,35 +41,39 @@ public class PropertyValue<T> {
}
/**
- * Returns if this is a function.
+ * Returns if this is a expression.
*
- * @return true if is a function, false if not
+ * @return true if this is a expression, false if not
*/
- public boolean isFunction() {
- return !isNull() && value instanceof Function;
+ public boolean isExpression() {
+ return !isNull() && value instanceof JsonArray;
}
/**
- * Returns if this is a value.
+ * Get the expression of the property.
*
- * @return true if is a value, false if not
+ * @return the property expression
*/
- public boolean isValue() {
- return !isNull() && !isFunction();
- }
-
@Nullable
- public Function<?, T> getFunction() {
- if (isFunction()) {
- // noinspection unchecked
- return (Function<?, T>) value;
+ public Expression getExpression() {
+ if (isExpression()) {
+ return Expression.Converter.convert((JsonArray) value);
} else {
- Timber.w("not a function, try value");
+ Timber.w("not a expression, try value");
return null;
}
}
/**
+ * Returns if this is a value.
+ *
+ * @return true if is a value, false if not
+ */
+ public boolean isValue() {
+ return !isNull() && !isExpression();
+ }
+
+ /**
* Get the value of the property.
*
* @return the property value
@@ -77,7 +82,7 @@ public class PropertyValue<T> {
public T getValue() {
if (isValue()) {
// noinspection unchecked
- return (T) value;
+ return value;
} else {
Timber.w("not a value, try function");
return null;
@@ -114,4 +119,4 @@ public class PropertyValue<T> {
public String toString() {
return String.format("%s: %s", name, value);
}
-}
+} \ No newline at end of file
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 a0f45535f6..0c7948f62a 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
@@ -4,10 +4,13 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
+import com.google.gson.JsonArray;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
/**
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 d0fb82dce5..6a2e131d7d 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
@@ -4,10 +4,13 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
+import com.google.gson.JsonArray;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
/**
@@ -69,26 +72,41 @@ public class SymbolLayer extends Layer {
}
/**
- * Set a single filter.
+ * Set a single expression filter.
*
- * @param filter the filter to set
+ * @param filter the expression filter to set
*/
- public void setFilter(Filter.Statement filter) {
+ public void setFilter(Expression filter) {
nativeSetFilter(filter.toArray());
}
/**
- * Set a single filter.
+ * Set a single expression filter.
*
- * @param filter the filter to set
+ * @param filter the expression filter to set
* @return This
*/
- public SymbolLayer withFilter(Filter.Statement filter) {
+ public SymbolLayer withFilter(Expression filter) {
setFilter(filter);
return this;
}
/**
+ * Get a single expression filter.
+ *
+ * @return the expression filter to get
+ */
+ @Nullable
+ public Expression getFilter() {
+ Expression expression = null;
+ JsonArray array = (JsonArray) nativeGetFilter();
+ if (array != null) {
+ expression = Expression.Converter.convert(array);
+ }
+ return expression;
+ }
+
+ /**
* Set a property or properties.
*
* @param properties the var-args properties
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 77fa11808e..851a85f3d6 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
@@ -9,10 +9,13 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.ColorInt;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
+import com.google.gson.JsonArray;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
/**
@@ -89,25 +92,40 @@ public class <%- camelize(type) %>Layer extends Layer {
}
/**
- * Set a single filter.
+ * Set a single expression filter.
*
- * @param filter the filter to set
+ * @param filter the expression filter to set
*/
- public void setFilter(Filter.Statement filter) {
+ public void setFilter(Expression filter) {
nativeSetFilter(filter.toArray());
}
/**
- * Set a single filter.
+ * Set a single expression filter.
*
- * @param filter the filter to set
+ * @param filter the expression filter to set
* @return This
*/
- public <%- camelize(type) %>Layer withFilter(Filter.Statement filter) {
+ public <%- camelize(type) %>Layer withFilter(Expression filter) {
setFilter(filter);
return this;
}
+ /**
+ * Get a single expression filter.
+ *
+ * @return the expression filter to get
+ */
+ @Nullable
+ public Expression getFilter() {
+ Expression expression = null;
+ JsonArray array = (JsonArray) nativeGetFilter();
+ if (array != null) {
+ expression = Expression.Converter.convert(array);
+ }
+ return expression;
+ }
+
<% } -%>
/**
* Set a property or properties.
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 283d4e4189..6480dde3c8 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
@@ -8,9 +8,7 @@ package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.ColorInt;
-import com.mapbox.mapboxsdk.style.functions.CameraFunction;
import com.mapbox.mapboxsdk.style.expressions.Expression;
-import com.mapbox.mapboxsdk.style.functions.Function;
import java.util.Locale;
@@ -31,18 +29,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("visibility", value);
}
- /**
- * Set the property visibility.
- *
- * @param <T> the function input type
- * @param function the visibility function
- * @return property wrapper around a String function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, String>> visibility(Function<T, String> function) {
- return new LayoutPropertyValue<>("visibility", function);
- }
-
<% for (const property of paintProperties) { -%>
<% if (property.type == 'color') { -%>
/**
@@ -76,35 +62,6 @@ public class PropertyFactory {
return new PaintPropertyValue<>("<%- property.name %>", expression);
}
-<% if (supportsPropertyFunction(property)) { -%>
-
- /**
- * <%- propertyFactoryMethodDoc(property) %>
- *
- * @param <T> the function input type
- * @param function a wrapper function for <%- propertyType(property) %>
- * @return property wrapper around a <%- propertyType(property) %> function
- */
- @Deprecated
- public static <T> PropertyValue<Function<T, <%- propertyType(property) %>>> <%- camelizeWithLeadingLowercase(property.name) %>(Function<T, <%- propertyType(property) %>> function) {
- return new PaintPropertyValue<>("<%- property.name %>", function);
- }
-
-<% } else if (supportsZoomFunction(property)) { -%>
-
- /**
- * <%- propertyFactoryMethodDoc(property) %>
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for <%- propertyType(property) %>
- * @return property wrapper around a <%- propertyType(property) %> function
- */
- @Deprecated
- public static <Z extends Number> PropertyValue<CameraFunction<Z, <%- propertyType(property) %>>> <%- camelizeWithLeadingLowercase(property.name) %>(CameraFunction<Z, <%- propertyType(property) %>> function) {
- return new PaintPropertyValue<>("<%- property.name %>", function);
- }
-
-<% } -%>
<% } -%>
<% for (const property of layoutProperties) { -%>
/**
@@ -127,33 +84,6 @@ public class PropertyFactory {
return new LayoutPropertyValue<>("<%- property.name %>", value);
}
-<% if (supportsPropertyFunction(property)) { -%>
-
- /**
- * <%- propertyFactoryMethodDoc(property) %>
- *
- * @param <T> the function input type
- * @param function a wrapper function for <%- propertyType(property) %>
- * @return property wrapper around a <%- propertyType(property) %> function
- */
- public static <T> PropertyValue<Function<T, <%- propertyType(property) %>>> <%- camelizeWithLeadingLowercase(property.name) %>(Function<T, <%- propertyType(property) %>> function) {
- return new LayoutPropertyValue<>("<%- property.name %>", function);
- }
-
-<% } else if (supportsZoomFunction(property)) { -%>
-
- /**
- * <%- propertyFactoryMethodDoc(property) %>
- *
- * @param <Z> the zoom parameter type
- * @param function a wrapper {@link CameraFunction} for <%- propertyType(property) %>
- * @return property wrapper around a <%- propertyType(property) %> function
- */
- public static <Z extends Number> PropertyValue<CameraFunction<Z, <%- propertyType(property) %>>> <%- camelizeWithLeadingLowercase(property.name) %>(CameraFunction<Z, <%- propertyType(property) %>> function) {
- return new LayoutPropertyValue<>("<%- property.name %>", function);
- }
-
-<% } -%>
<% } -%>
public static String colorToRgbaString(@ColorInt int value) {
return String.format(Locale.US,"rgba(%d, %d, %d, %d)",
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Light.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Light.java
index 8f23e7d01e..7df48001cc 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Light.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Light.java
@@ -48,7 +48,7 @@ public class Light {
}
/**
- * Set the Position property. Position of the light source relative to lit (extruded) geometries, in [r radial coordinate, a azimuthal angle, p polar angle] where r indicates the distance from the center of the base of an object to its light, a indicates the position of the light relative to 0° (0° when `light.anchor` is set to `viewport` corresponds to the top of the viewport, or 0° when `light.anchor` is set to `map` corresponds to due north, and degrees proceed clockwise), and p indicates the height of the light (from 0°, directly above, to 180°, directly below).
+ * Set the Position property. Position of the light source relative to lit (extruded) geometries, in [r radial coordinate, a azimuthal angle, p polar angle] where r indicates the distance from the center of the base of an object to its light, a indicates the position of the light relative to 0&#xB0; (0&#xB0; when `light.anchor` is set to `viewport` corresponds to the top of the viewport, or 0&#xB0; when `light.anchor` is set to `map` corresponds to due north, and degrees proceed clockwise), and p indicates the height of the light (from 0&#xB0;, directly above, to 180&#xB0;, directly below).
*
* @param position of the light
*/
@@ -57,7 +57,7 @@ public class Light {
}
/**
- * Get the Position property. Position of the light source relative to lit (extruded) geometries, in [r radial coordinate, a azimuthal angle, p polar angle] where r indicates the distance from the center of the base of an object to its light, a indicates the position of the light relative to 0° (0° when `light.anchor` is set to `viewport` corresponds to the top of the viewport, or 0° when `light.anchor` is set to `map` corresponds to due north, and degrees proceed clockwise), and p indicates the height of the light (from 0°, directly above, to 180°, directly below).
+ * Get the Position property. Position of the light source relative to lit (extruded) geometries, in [r radial coordinate, a azimuthal angle, p polar angle] where r indicates the distance from the center of the base of an object to its light, a indicates the position of the light relative to 0&#xB0; (0&#xB0; when `light.anchor` is set to `viewport` corresponds to the top of the viewport, or 0&#xB0; when `light.anchor` is set to `map` corresponds to due north, and degrees proceed clockwise), and p indicates the height of the light (from 0&#xB0;, directly above, to 180&#xB0;, directly below).
*
* @return position as Position
*/
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Position.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Position.java
index cd6218d3e2..00f8486a1c 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Position.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/light/Position.java
@@ -5,11 +5,11 @@ package com.mapbox.mapboxsdk.style.light;
* <p>
* The position is constructed out of a radial coordinate, an azimuthal angle and a polar angle.
* where the radial coordinate indicates the distance from the center of the base of an object to its light, the
- * azimuthal angle indicates the position of the light relative to 0° (0° when
+ * azimuthal angle indicates the position of the light relative to 0&#xB0; (0&#xB0; when
* {@link com.mapbox.mapboxsdk.style.layers.Property.ANCHOR} is set to viewport corresponds to the top of the
- * viewport, or 0° when {@link com.mapbox.mapboxsdk.style.layers.Property.ANCHOR} is set to map corresponds to due
+ * viewport, or 0&#xB0; when {@link com.mapbox.mapboxsdk.style.layers.Property.ANCHOR} is set to map corresponds to due
* north, and degrees proceed clockwise), and polar indicates the height of the light
- * (from 0°, directly above, to 180°, directly below).
+ * (from 0&#xB0;, directly above, to 180&#xB0;, directly below).
*/
public class Position {
@@ -21,7 +21,7 @@ public class Position {
* Creates a Position from a radial coordinate, an azimuthal angle and a polar angle.
*
* @param radialCoordinate the distance from the center of the base of an object to its light
- * @param azimuthalAngle the position of the light relative to 0°
+ * @param azimuthalAngle the position of the light relative to 0&#xB0;
* @param polarAngle the height of the light
*/
public Position(float radialCoordinate, float azimuthalAngle, float polarAngle) {
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.java
index 1b0999ae2e..21a34f6064 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.java
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/sources/CustomGeometrySource.java
@@ -8,7 +8,7 @@ import android.support.annotation.WorkerThread;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.mapboxsdk.geometry.LatLngBounds;
-import com.mapbox.mapboxsdk.style.layers.Filter;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
@@ -94,11 +94,11 @@ public class CustomGeometrySource extends Source {
/**
* Queries the source for features.
*
- * @param filter an optional filter statement to filter the returned Features
+ * @param filter an optional filter expression to filter the returned Features
* @return the features
*/
@NonNull
- public List<Feature> querySourceFeatures(@Nullable Filter.Statement filter) {
+ public List<Feature> querySourceFeatures(@Nullable Expression filter) {
Feature[] features = querySourceFeatures(filter != null ? filter.toArray() : null);
return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
}
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 5c740554cd..efacc18741 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
@@ -7,7 +7,7 @@ import android.support.annotation.UiThread;
import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.geojson.Geometry;
-import com.mapbox.mapboxsdk.style.layers.Filter;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import java.net.URL;
import java.util.ArrayList;
@@ -187,7 +187,7 @@ public class GeoJsonSource extends Source {
*
* @param geometry the GeoJSON {@link Geometry} to set
*/
- public void setGeoJson(Geometry<?> geometry) {
+ public void setGeoJson(Geometry geometry) {
nativeSetGeometry(geometry);
}
@@ -238,11 +238,11 @@ public class GeoJsonSource extends Source {
/**
* Queries the source for features.
*
- * @param filter an optional filter statement to filter the returned Features
+ * @param filter an optional filter expression to filter the returned Features
* @return the features
*/
@NonNull
- public List<Feature> querySourceFeatures(@Nullable Filter.Statement filter) {
+ public List<Feature> querySourceFeatures(@Nullable Expression filter) {
Feature[] features = querySourceFeatures(filter != null ? filter.toArray() : null);
return features != null ? Arrays.asList(features) : new ArrayList<Feature>();
}
@@ -259,7 +259,7 @@ public class GeoJsonSource extends Source {
private native void nativeSetFeature(Feature feature);
- private native void nativeSetGeometry(Geometry<?> geometry);
+ private native void nativeSetGeometry(Geometry geometry);
private native Feature[] querySourceFeatures(Object[] filter);
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 54e4e5f5d3..25df2d91e7 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
@@ -9,6 +9,7 @@ import java.util.Map;
/**
* Tile set, allows using TileJson specification as source.
+ * Note that `encoding` is only relevant to `raster-dem` sources, and is not supported in the TileJson spec.
*
* @see <a href="https://github.com/mapbox/tilejson-spec/tree/master/2.1.0">The tileset specification</a>
*/
@@ -28,6 +29,7 @@ public class TileSet {
private Float maxZoom;
private Float[] bounds;
private Float[] center;
+ private String encoding;
/**
* @param tilejson A semver.org style version number. Describes the version of the TileJSON spec that is implemented
@@ -246,6 +248,20 @@ public class TileSet {
this.bounds = bounds;
}
+ public String getEncoding() {
+ return encoding;
+ }
+
+ /**
+ * Default: "mapbox". The encoding formula for a raster-dem tileset.
+ * Supported values are "mapbox" and "terrarium".
+ *
+ * @param encoding the String encoding formula to set
+ */
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
public Float[] getCenter() {
return center;
}
@@ -313,6 +329,10 @@ public class TileSet {
if (center != null) {
result.put("center", center);
}
+ if (encoding != null) {
+ result.put("encoding", encoding);
+ }
+
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 62b08a90ed..d82eaaa1c7 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
@@ -6,7 +6,7 @@ import android.support.annotation.Size;
import android.support.annotation.UiThread;
import com.mapbox.geojson.Feature;
-import com.mapbox.mapboxsdk.style.layers.Filter;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import java.net.URL;
import java.util.ArrayList;
@@ -64,12 +64,12 @@ public class VectorSource extends Source {
* Queries the source for features.
*
* @param sourceLayerIds the source layer identifiers. At least one must be specified.
- * @param filter an optional filter statement to filter the returned Features
+ * @param filter an optional filter expression to filter the returned Features
* @return the features
*/
@NonNull
public List<Feature> querySourceFeatures(@Size(min = 1) String[] sourceLayerIds,
- @Nullable Filter.Statement filter) {
+ @Nullable Expression filter) {
Feature[] features = querySourceFeatures(
sourceLayerIds,
filter != null ? filter.toArray() : null);
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/text/package-info.java b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/text/package-info.java
new file mode 100644
index 0000000000..52c7014bce
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/text/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * Contains the Mapbox Maps Android Text API classes.
+ */
+package com.mapbox.mapboxsdk.text;
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
index 007880acd1..08d39d6b3b 100644
--- 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
@@ -1,11 +1,8 @@
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;
@@ -45,25 +42,6 @@ public class MapFragmentUtils {
// 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/res-public/values/public.xml b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
index 412d8c5d9b..fda37dc2df 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res-public/values/public.xml
@@ -75,6 +75,7 @@
<!-- Use TextureView-->
<public name="mapbox_renderTextureMode" type="attr" />
+ <public name="mapbox_renderTextureTranslucentSurface" type="attr" />
<public name="mapbox_enableTilePrefetch" type="attr" />
<public name="mapbox_enableZMediaOverlay" type="attr" />
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml
index 29ff49f47e..8dd4a858df 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/layout/mapbox_mapview_internal.xml
@@ -8,12 +8,6 @@
android:background="@android:color/transparent"
android:contentDescription="@null"/>
- <com.mapbox.mapboxsdk.maps.widgets.MyLocationView
- android:id="@+id/userLocationView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:contentDescription="@string/mapbox_myLocationViewContentDescription"/>
-
<com.mapbox.mapboxsdk.maps.widgets.CompassView
android:id="@+id/compassView"
android:layout_width="wrap_content"
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values-cs/strings.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values-cs/strings.xml
new file mode 100644
index 0000000000..094fb830b2
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values-cs/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="mapbox_compassContentDescription">Kompas. Nastavit natočení mapy k severu.</string>
+ <string name="mapbox_attributionsIconContentDescription">Atributy. Zobrazit nastavení atributů.</string>
+ <string name="mapbox_myLocationViewContentDescription">Zobrazení polohy. Zobrazit umístění na mapě.</string>
+ <string name="mapbox_mapActionDescription">Zobrazení mapy vytvořené s Mapbox. Posunout tažením dvěma prsty. Změnit velikost roztažením dvou prstů.</string>
+ <string name="mapbox_attributionsDialogTitle">Mapbox Maps SDK pro Android</string>
+ <string name="mapbox_attributionTelemetryTitle">Udělat mapy Mapbox lepšími</string>
+ <string name="mapbox_attributionTelemetryMessage">Pomáhat udělat OpenStreetMap a Mapbox mapy lepšími poskytnutím anonymních dat o využití.</string>
+ <string name="mapbox_attributionTelemetryPositive">Souhlasit</string>
+ <string name="mapbox_attributionTelemetryNegative">Odmítnout</string>
+ <string name="mapbox_attributionTelemetryNeutral">Více informací</string>
+ <string name="mapbox_attributionErrorNoBrowser">Na zařízení není nainstalován prohlížeč obsahu internetu, webovou stránku nelze zobrazit.</string>
+ <string name="mapbox_offline_error_region_definition_invalid">Pokud OfflineRegionDefinition neodpovídá hranicím: %s</string>
+ <string name="mapbox_telemetrySettings">Nastavení telemetrie</string>
+ </resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values-he/strings.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values-he/strings.xml
new file mode 100644
index 0000000000..11b20f5dc5
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values-he/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="mapbox_compassContentDescription">מצפן. הפעל בכדי לקבע את כיוון המפה צפונה.</string>
+ <string name="mapbox_attributionsIconContentDescription">סמל שיוך. הפעל כדי להציג תיבת דו-שיח של שיוך.</string>
+ <string name="mapbox_myLocationViewContentDescription">סמן מיקום. מציג את המיקום הנוכחי שלך על המפה.</string>
+ <string name="mapbox_mapActionDescription">מציג מפה שנוצרה עם Mapbox. גלול באמצעות גרירה עם שתי אצבעות, זום באמצעות צביטה עם שתי אצבעות.</string>
+ <string name="mapbox_attributionsDialogTitle">Mapbox Maps SDK for Android</string>
+ <string name="mapbox_attributionTelemetryTitle">שפר את המפות של Mapbox </string>
+ <string name="mapbox_attributionTelemetryMessage">אתם מסייעים לשפר את המפות של OpenStreetMap ו Mapbox באמצעות שיתוף אנונימי של נתוני השימוש.</string>
+ <string name="mapbox_attributionTelemetryPositive">מסכים/מה</string>
+ <string name="mapbox_attributionTelemetryNegative">לא מסכים/מה</string>
+ <string name="mapbox_attributionTelemetryNeutral">מידע נוסף</string>
+ <string name="mapbox_attributionErrorNoBrowser">לא מותקן דפדפן אינטרנט במכשיר, לא ניתן לפתוח את דף האינטרנט.</string>
+ <string name="mapbox_offline_error_region_definition_invalid">בתנאי ש- OfflineRegionDefinition אינו מתאים לגבולות העולם: %s</string>
+ <string name="mapbox_telemetrySettings">הגדרות טלמטריות</string>
+ </resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values-pt-rPT/strings.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values-pt-rPT/strings.xml
new file mode 100644
index 0000000000..02941aab5a
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values-pt-rPT/strings.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+ <string name="mapbox_compassContentDescription">Compasso do mapa. Ativar para virar o mapa para Norte.</string>
+ <string name="mapbox_attributionsIconContentDescription">Ícone de atribuição. Ativar para mostrar a janela de atribuição.</string>
+ <string name="mapbox_myLocationViewContentDescription">Vista de localização. Isto mostra a sua localização no mapa.</string>
+ <string name="mapbox_mapActionDescription">A mostrar um Mapa criado com Mapbox. Desloque arrastanto com 2 dedos. Zoom afastando ou aproximando os 2 dedos.</string>
+ <string name="mapbox_attributionsDialogTitle">Mapas Mapbox SDK para Android</string>
+ <string name="mapbox_attributionTelemetryTitle">Torne os Mapas Mapbox Melhores</string>
+ <string name="mapbox_attributionTelemetryMessage">Está a ajudar a tornar os mapas OpenStreetMap e Mapbox melhores contribuindo com dados de utilização tornados anónimos.</string>
+ <string name="mapbox_attributionTelemetryPositive">Concordo</string>
+ <string name="mapbox_attributionTelemetryNegative">Não concordo</string>
+ <string name="mapbox_attributionTelemetryNeutral">Mais informações</string>
+ <string name="mapbox_attributionErrorNoBrowser">Não está nenhum navegador de Internet instalado no dispositivo. Não é possível abrir a página web.</string>
+ <string name="mapbox_offline_error_region_definition_invalid">O OfflineRegionDefinition não cabe nos limites do mundo: %s</string>
+ <string name="mapbox_telemetrySettings">Definições de Telemetria</string>
+ </resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values-ru/strings.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values-ru/strings.xml
index 39880d56ba..a274125257 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values-ru/strings.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values-ru/strings.xml
@@ -1,15 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <string name="mapbox_compassContentDescription">Компас. Активируйте, чтобы повернуть карту на Север.</string>
- <string name="mapbox_attributionsIconContentDescription">Иконка атрибутов. Активируйте, чтобы показать диалог.</string>
- <string name="mapbox_myLocationViewContentDescription">Местоположение. Отображает ваше местоположение на карте.</string>
- <string name="mapbox_mapActionDescription">Отображает карту, созданную при помощи Mapbox. Протисните при помощи двух пальцев. Приблизьте, соединением пальцев. </string>
- <string name="mapbox_attributionsDialogTitle">Mapbox Android SDK</string>
+ <string name="mapbox_compassContentDescription">Компас. Активируйте, чтобы развернуть карту на север.</string>
+ <string name="mapbox_attributionsIconContentDescription">Значок атрибутов. Активируйте, чтобы показать диалог.</string>
+ <string name="mapbox_myLocationViewContentDescription">Местоположение. Отображает вашу позицию на карте.</string>
+ <string name="mapbox_mapActionDescription">Отображает карту, созданную при помощи Mapbox. Пролистывайте двумя пальцами. Меняйте масштаб сведением пальцев.</string>
+ <string name="mapbox_attributionsDialogTitle">Mapbox Maps SDK для Android</string>
<string name="mapbox_attributionTelemetryTitle">Сделать карты Mapbox лучше</string>
- <string name="mapbox_attributionTelemetryMessage">Вы помогаете сделать карты OpenStreetMap и Mapbox лучше путем предоставления анонимных данных об использовании.</string>
+ <string name="mapbox_attributionTelemetryMessage">Вы помогаете улучшать карты OpenStreetMap и Mapbox, предоставляя обезличенные данные об использовании.</string>
<string name="mapbox_attributionTelemetryPositive">Согласен</string>
<string name="mapbox_attributionTelemetryNegative">Не согласен</string>
<string name="mapbox_attributionTelemetryNeutral">Дополнительная информация</string>
- <string name="mapbox_offline_error_region_definition_invalid">Запрошенный OfflineRegionDefinition не входит в допустимые границы: %s</string>
-
+ <string name="mapbox_attributionErrorNoBrowser">На устройстве нет веб-браузера, нельзя показать веб-страницу.</string>
+ <string name="mapbox_offline_error_region_definition_invalid">Запрошенный OfflineRegionDefinition не входит в допустимые границы: %s</string>
+ <string name="mapbox_telemetrySettings">Настройки телеметрии</string>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
index 97adce8a4e..f0b80e46e1 100644
--- a/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
+++ b/platform/android/MapboxGLAndroidSDK/src/main/res/values/attrs.xml
@@ -117,6 +117,7 @@
<!-- Use TextureView-->
<attr name="mapbox_renderTextureMode" format="boolean"/>
+ <attr name="mapbox_renderTextureTranslucentSurface" format="boolean"/>
<attr name="mapbox_enableTilePrefetch" format="boolean"/>
<attr name="mapbox_enableZMediaOverlay" format="boolean"/>
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/MapboxTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/MapboxTest.java
index d9e3ae427d..6ee5c157b9 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/MapboxTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/MapboxTest.java
@@ -5,7 +5,6 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import com.mapbox.mapboxsdk.exceptions.MapboxConfigurationException;
-import com.mapbox.android.core.location.LocationEngine;
import org.junit.Before;
import org.junit.Test;
@@ -25,13 +24,11 @@ public class MapboxTest {
private Context context;
private Context appContext;
- private LocationEngine locationSource;
@Before
public void before() {
context = mock(Context.class);
appContext = mock(Context.class);
- locationSource = mock(LocationEngine.class);
when(context.getApplicationContext()).thenReturn(appContext);
}
@@ -83,7 +80,7 @@ public class MapboxTest {
}
private void injectMapboxSingleton(String accessToken) {
- Mapbox mapbox = new Mapbox(appContext, accessToken, locationSource);
+ Mapbox mapbox = new Mapbox(appContext, accessToken);
try {
Field field = Mapbox.class.getDeclaredField("INSTANCE");
field.setAccessible(true);
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
index f03bbdb11c..e072f07fb9 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/geometry/LatLngBoundsTest.java
@@ -111,6 +111,14 @@ public class LatLngBoundsTest {
}
@Test
+ public void zeroLongitudeSpan() {
+ latLngBounds = LatLngBounds.from(10, 10, -10, 10);
+ LatLngSpan latLngSpan = latLngBounds.getSpan();
+ assertEquals("LatLngSpan should be shortest distance", new LatLngSpan(20, 0),
+ latLngSpan);
+ }
+
+ @Test
public void nearDateLineCenter1() {
latLngBounds = LatLngBounds.from(10, -175, -10, 165);
LatLng center = latLngBounds.getCenter();
@@ -145,6 +153,19 @@ public class LatLngBoundsTest {
assertEquals("Center should match", new LatLng(0, 90), center);
}
+ @Test
+ public void centerForBoundsWithSameLongitude() {
+ latLngBounds = LatLngBounds.from(10, 10, -10, 10);
+ LatLng center = latLngBounds.getCenter();
+ assertEquals("Center should match", new LatLng(0, 10), center);
+ }
+
+ @Test
+ public void centerForBoundsWithSameLatitude() {
+ latLngBounds = LatLngBounds.from(10, 10, 10, -10);
+ LatLng center = latLngBounds.getCenter();
+ assertEquals("Center should match", new LatLng(10, 0), center);
+ }
@Test
public void center() {
@@ -197,6 +218,27 @@ public class LatLngBoundsTest {
}
@Test
+ public void includesOrderDoesNotMatter() {
+ LatLngBounds sameLongitudeFirst = new LatLngBounds.Builder()
+ .include(new LatLng(50, 10)) // southWest
+ .include(new LatLng(60, 10))
+ .include(new LatLng(60, 20)) // northEast
+ .include(new LatLng(50, 20))
+ .include(new LatLng(50, 10)) // southWest again
+ .build();
+
+ LatLngBounds sameLatitudeFirst = new LatLngBounds.Builder()
+ .include(new LatLng(50, 20))
+ .include(new LatLng(50, 10)) // southWest
+ .include(new LatLng(60, 10))
+ .include(new LatLng(60, 20)) // northEast
+ .include(new LatLng(50, 20))
+ .build();
+
+ assertEquals(sameLatitudeFirst, sameLongitudeFirst);
+ }
+
+ @Test
public void includesOverDateline1() {
LatLngBounds latLngBounds = new LatLngBounds.Builder()
@@ -338,6 +380,27 @@ public class LatLngBoundsTest {
}
@Test
+ public void unionOverDateLine() {
+ LatLngBounds latLngBounds1 = new LatLngBounds.Builder()
+ .include(new LatLng(10, 170))
+ .include(new LatLng(0, 160))
+ .build();
+
+ LatLngBounds latLngBounds2 = new LatLngBounds.Builder()
+ .include(new LatLng(0, -170))
+ .include(new LatLng(-10, -160))
+ .build();
+
+ assertEquals("outer union should match",
+ latLngBounds1.union(latLngBounds2),
+ new LatLngBounds.Builder()
+ .include(new LatLng(10, 160))
+ .include(new LatLng(-10, -160))
+ .build());
+ }
+
+
+ @Test
public void northWest() {
double minLat = 5;
double minLon = 6;
@@ -496,4 +559,11 @@ public class LatLngBoundsTest {
exception.expectMessage("longitude must not be infinite");
LatLngBounds.from(20, 20, 0, Double.POSITIVE_INFINITY);
}
+
+ @Test
+ public void testConstructorCheckLatSouthGreaterLatNorth() {
+ exception.expect(IllegalArgumentException.class);
+ exception.expectMessage("LatSouth cannot be less than latNorth");
+ LatLngBounds.from(0, 20, 20, 0);
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java
index 65bdff41ab..9dd0ca9285 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapOptionsTest.java
@@ -119,13 +119,6 @@ public class MapboxMapOptionsTest {
}
@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());
@@ -176,18 +169,6 @@ public class MapboxMapOptionsTest {
}
@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 testPrefetchesTiles() {
// Default value
assertTrue(new MapboxMapOptions().getPrefetchesTiles());
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
index d61947f00e..9a323a1d75 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/MapboxMapTest.java
@@ -2,7 +2,6 @@ package com.mapbox.mapboxsdk.maps;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
import org.junit.After;
import org.junit.Before;
@@ -20,8 +19,6 @@ public class MapboxMapTest {
mapboxMap = new MapboxMap(mock(NativeMapView.class),
mock(Transform.class),
mock(UiSettings.class),
- mock(TrackingSettings.class),
- mock(MyLocationViewSettings.class),
mock(Projection.class),
mock(MapboxMap.OnGesturesManagerInteractionListener.class),
mock(AnnotationManager.class),
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/TrackingSettingsTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/TrackingSettingsTest.java
deleted file mode 100644
index de5f364a5b..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/TrackingSettingsTest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-package com.mapbox.mapboxsdk.maps;
-
-import android.Manifest;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.graphics.PointF;
-
-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.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.atLeast;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class TrackingSettingsTest {
-
- @InjectMocks
- MyLocationView myLocationView = mock(MyLocationView.class);
-
- @InjectMocks
- UiSettings uiSettings = mock(UiSettings.class);
-
- @InjectMocks
- FocalPointChangeListener focalPointChangeListener = mock(FocalPointChangeListener.class);
-
- @InjectMocks
- TrackingSettings.CameraZoomInvalidator zoomInvalidator = mock(TrackingSettings.CameraZoomInvalidator.class);
-
- private TrackingSettings trackingSettings;
-
- @Before
- public void beforeTest() {
- trackingSettings = new TrackingSettings(myLocationView, uiSettings, focalPointChangeListener, zoomInvalidator);
- }
-
- @Test
- public void testSanity() {
- assertNotNull("trackingsettings should not be null", trackingSettings);
- }
-
- @Test
- public void testDismissTrackingModesOnGesture() {
- trackingSettings.setDismissAllTrackingOnGesture(false);
- assertFalse("DismissTrackingOnGesture should be false", trackingSettings.isAllDismissTrackingOnGesture());
- }
-
- @Test
- public void testValidateGesturesForTrackingModes() {
- trackingSettings.setDismissAllTrackingOnGesture(false);
- trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
- assertFalse("DismissTrackingOnGesture should be false", trackingSettings.isAllDismissTrackingOnGesture());
- }
-
- @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());
- }
-
- @Test
- public void testCameraZoomTo2forTracking() {
- trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
- verify(zoomInvalidator, atLeast(1)).zoomTo(2.0);
- }
-
- @Test
- public void testFocalPointChangeForTracking() {
- final float centerX = 32.3f;
- final float centerY = 46.3f;
- final PointF pointF = new PointF(centerX, centerY);
- when(myLocationView.getCenter()).thenReturn(pointF);
-
- trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
- verify(focalPointChangeListener, atLeast(1)).onFocalPointChanged(pointF);
- }
-
- @Test
- public void testFocalPointChangeForNonTracking() {
- trackingSettings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_NONE);
- verify(focalPointChangeListener, atLeast(1)).onFocalPointChanged(null);
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
index fbe00b4dce..cfce56e6e9 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/UiSettingsTest.java
@@ -181,13 +181,6 @@ public class UiSettingsTest {
}
@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());
@@ -196,14 +189,6 @@ public class UiSettingsTest {
}
@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());
@@ -216,13 +201,6 @@ public class UiSettingsTest {
}
@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());
@@ -231,14 +209,6 @@ public class UiSettingsTest {
}
@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());
@@ -251,13 +221,6 @@ public class UiSettingsTest {
}
@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());
@@ -266,14 +229,6 @@ public class UiSettingsTest {
}
@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());
@@ -298,13 +253,6 @@ public class UiSettingsTest {
}
@Test
- public void testDoubleTapGestureChange() {
- assertEquals("Default state should be true", true, uiSettings.isDoubleTapGestureChangeAllowed());
- uiSettings.setDoubleTapGestureChangeAllowed(false);
- assertEquals("State should have been changed", false, uiSettings.isDoubleTapGestureChangeAllowed());
- }
-
- @Test
public void testDoubleTapGestureChangeAllowed() {
uiSettings.setDoubleTapGesturesEnabled(false);
assertEquals("DoubleTap gesture should be false", false, uiSettings.isDoubleTapGesturesEnabled());
@@ -313,14 +261,6 @@ public class UiSettingsTest {
}
@Test
- public void testDoubleTapGestureChangeDisallowed() {
- assertEquals("DoubleTap gesture should be true", true, uiSettings.isDoubleTapGesturesEnabled());
- uiSettings.setDoubleTapGestureChangeAllowed(false);
- uiSettings.setDoubleTapGesturesEnabled(false);
- assertEquals("DoubleTap gesture change should be ignored", true, uiSettings.isDoubleTapGesturesEnabled());
- }
-
- @Test
public void testScrollGesturesEnabled() {
uiSettings.setScrollGesturesEnabled(true);
assertEquals("Scroll gesture should be enabled", true, uiSettings.isScrollGesturesEnabled());
@@ -333,13 +273,6 @@ public class UiSettingsTest {
}
@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());
@@ -348,11 +281,82 @@ public class UiSettingsTest {
}
@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());
+ public void testScaleVelocityAnimationEnabled() {
+ uiSettings.setScaleVelocityAnimationEnabled(true);
+ assertEquals("Scale velocity animation should be enabled", true, uiSettings.isScaleVelocityAnimationEnabled());
+ }
+
+ @Test
+ public void testScaleVelocityAnimationDisabled() {
+ uiSettings.setScaleVelocityAnimationEnabled(false);
+ assertEquals("Scale velocity animation should be disabled", false, uiSettings.isScaleVelocityAnimationEnabled());
+ }
+
+ @Test
+ public void testRotateVelocityAnimationEnabled() {
+ uiSettings.setRotateVelocityAnimationEnabled(true);
+ assertEquals("Rotate velocity animation should be enabled", true, uiSettings.isRotateVelocityAnimationEnabled());
+ }
+
+ @Test
+ public void testRotateVelocityAnimationDisabled() {
+ uiSettings.setRotateVelocityAnimationEnabled(false);
+ assertEquals("Rotate velocity animation should be disabled", false, uiSettings.isRotateVelocityAnimationEnabled());
+ }
+
+ @Test
+ public void testFlingVelocityAnimationEnabled() {
+ uiSettings.setFlingVelocityAnimationEnabled(true);
+ assertEquals("Fling velocity animation should be enabled", true, uiSettings.isFlingVelocityAnimationEnabled());
+ }
+
+ @Test
+ public void testFlingVelocityAnimationDisabled() {
+ uiSettings.setFlingVelocityAnimationEnabled(false);
+ assertEquals("Fling velocity animation should be disabled", false, uiSettings.isFlingVelocityAnimationEnabled());
+ }
+
+ @Test
+ public void testAllVelocityAnimationsEnabled() {
+ uiSettings.setAllVelocityAnimationsEnabled(true);
+ assertEquals("Scale velocity animation should be enabled", true, uiSettings.isScaleVelocityAnimationEnabled());
+ assertEquals("Rotate velocity animation should be enabled", true, uiSettings.isRotateVelocityAnimationEnabled());
+ assertEquals("Fling velocity animation should be enabled", true, uiSettings.isFlingVelocityAnimationEnabled());
+ }
+
+ @Test
+ public void testAllVelocityAnimationsDisabled() {
+ uiSettings.setAllVelocityAnimationsEnabled(false);
+ assertEquals("Scale velocity animation should be disabled", false, uiSettings.isScaleVelocityAnimationEnabled());
+ assertEquals("Rotate velocity animation should be disabled", false, uiSettings.isRotateVelocityAnimationEnabled());
+ assertEquals("Fling velocity animation should be disabled", false, uiSettings.isFlingVelocityAnimationEnabled());
+ }
+
+ @Test
+ public void testIncreaseRotateThresholdWhenScalingEnabled() {
+ uiSettings.setIncreaseRotateThresholdWhenScaling(true);
+ assertEquals("Rotate threshold increase should be enabled", true,
+ uiSettings.isIncreaseRotateThresholdWhenScaling());
+ }
+
+ @Test
+ public void testIncreaseRotateThresholdWhenScalingDisabled() {
+ uiSettings.setIncreaseRotateThresholdWhenScaling(false);
+ assertEquals("Rotate threshold increase should be disabled", false,
+ uiSettings.isIncreaseRotateThresholdWhenScaling());
+ }
+
+ @Test
+ public void testIncreaseScaleThresholdWhenRotatingEnabled() {
+ uiSettings.setIncreaseScaleThresholdWhenRotating(true);
+ assertEquals("Scale threshold increase should be enabled", true, uiSettings.isIncreaseScaleThresholdWhenRotating());
+ }
+
+ @Test
+ public void testIncreaseScaleThresholdWhenRotatingDisabled() {
+ uiSettings.setIncreaseScaleThresholdWhenRotating(false);
+ assertEquals("Scale threshold increase should be disabled", false,
+ uiSettings.isIncreaseScaleThresholdWhenRotating());
}
@Test
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettingsTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettingsTest.java
deleted file mode 100644
index c9ce19dc85..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/maps/widgets/MyLocationViewSettingsTest.java
+++ /dev/null
@@ -1,106 +0,0 @@
-package com.mapbox.mapboxsdk.maps.widgets;
-
-import android.graphics.Color;
-import android.graphics.drawable.Drawable;
-
-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;
-import org.mockito.InjectMocks;
-
-import java.util.Arrays;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertNotNull;
-import static junit.framework.Assert.assertTrue;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class MyLocationViewSettingsTest {
-
- @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/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java
index c0b7832727..45833e8556 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/expressions/ExpressionTest.java
@@ -2,12 +2,11 @@ package com.mapbox.mapboxsdk.style.expressions;
import android.graphics.Color;
-import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
-
import org.junit.Test;
import java.util.Arrays;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.abs;
import static com.mapbox.mapboxsdk.style.expressions.Expression.acos;
import static com.mapbox.mapboxsdk.style.expressions.Expression.all;
import static com.mapbox.mapboxsdk.style.expressions.Expression.any;
@@ -16,6 +15,7 @@ import static com.mapbox.mapboxsdk.style.expressions.Expression.asin;
import static com.mapbox.mapboxsdk.style.expressions.Expression.at;
import static com.mapbox.mapboxsdk.style.expressions.Expression.atan;
import static com.mapbox.mapboxsdk.style.expressions.Expression.bool;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.ceil;
import static com.mapbox.mapboxsdk.style.expressions.Expression.coalesce;
import static com.mapbox.mapboxsdk.style.expressions.Expression.color;
import static com.mapbox.mapboxsdk.style.expressions.Expression.concat;
@@ -26,6 +26,7 @@ import static com.mapbox.mapboxsdk.style.expressions.Expression.downcase;
import static com.mapbox.mapboxsdk.style.expressions.Expression.e;
import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.floor;
import static com.mapbox.mapboxsdk.style.expressions.Expression.geometryType;
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
import static com.mapbox.mapboxsdk.style.expressions.Expression.gt;
@@ -58,6 +59,7 @@ import static com.mapbox.mapboxsdk.style.expressions.Expression.product;
import static com.mapbox.mapboxsdk.style.expressions.Expression.properties;
import static com.mapbox.mapboxsdk.style.expressions.Expression.rgb;
import static com.mapbox.mapboxsdk.style.expressions.Expression.rgba;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.round;
import static com.mapbox.mapboxsdk.style.expressions.Expression.sin;
import static com.mapbox.mapboxsdk.style.expressions.Expression.sqrt;
import static com.mapbox.mapboxsdk.style.expressions.Expression.step;
@@ -75,6 +77,7 @@ import static com.mapbox.mapboxsdk.style.expressions.Expression.typeOf;
import static com.mapbox.mapboxsdk.style.expressions.Expression.upcase;
import static com.mapbox.mapboxsdk.style.expressions.Expression.var;
import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.lineOpacity;
import static junit.framework.Assert.assertTrue;
import static org.junit.Assert.assertEquals;
@@ -113,7 +116,7 @@ public class ExpressionTest {
@Test
public void testToRgba() throws Exception {
- Object[] expected = new Object[] {"to-rgba", PropertyFactory.colorToRgbaString(Color.RED)};
+ Object[] expected = new Object[] {"to-rgba", new Object[] {"to-color", "rgba(255, 0, 0, 255)"}};
Object[] actual = toRgba(color(Color.RED)).toArray();
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
}
@@ -128,7 +131,7 @@ public class ExpressionTest {
@Test
public void testEqLiteral() throws Exception {
Object[] expected = new Object[] {"==", 1, 1};
- Object[] actual = eq(1, 1).toArray();
+ Object[] actual = eq(literal(1), 1).toArray();
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
}
@@ -142,7 +145,7 @@ public class ExpressionTest {
@Test
public void testNeqLiteral() throws Exception {
Object[] expected = new Object[] {"!=", 0, 1};
- Object[] actual = neq(0, 1).toArray();
+ Object[] actual = neq(literal(0), 1).toArray();
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
}
@@ -156,7 +159,7 @@ public class ExpressionTest {
@Test
public void testGtLiteral() throws Exception {
Object[] expected = new Object[] {">", 0, 1};
- Object[] actual = gt(0, 1).toArray();
+ Object[] actual = gt(literal(0), 1).toArray();
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
}
@@ -170,7 +173,7 @@ public class ExpressionTest {
@Test
public void testLtLiteral() throws Exception {
Object[] expected = new Object[] {"<", 1, 0};
- Object[] actual = lt(1, 0).toArray();
+ Object[] actual = lt(literal(1), 0).toArray();
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
}
@@ -184,7 +187,7 @@ public class ExpressionTest {
@Test
public void testGteLiteral() throws Exception {
Object[] expected = new Object[] {">=", 1, 1};
- Object[] actual = gte(1, 1).toArray();
+ Object[] actual = gte(literal(1), 1).toArray();
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
}
@@ -198,7 +201,7 @@ public class ExpressionTest {
@Test
public void testLteLiteral() throws Exception {
Object[] expected = new Object[] {"<=", 1, 1};
- Object[] actual = lte(1, 1).toArray();
+ Object[] actual = lte(literal(1), 1).toArray();
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
}
@@ -264,12 +267,46 @@ public class ExpressionTest {
@Test
public void testMatch() throws Exception {
- Object[] labelZero = new Object[] {"a", "output"};
- Object[] labelOne = new Object[] {"b", "output2"};
- Object[] labelTwo = new Object[] {"c", "output3"};
+ String input = "input";
+ String[] labels = new String[] {"a", "b", "c"};
+ String[] outputs = new String[] {"1", "2", "3"};
+ String defaultOutput = "0";
+
+ Object[] expected = new Object[] {"match", input,
+ labels[0], outputs[0],
+ labels[1], outputs[1],
+ labels[2], outputs[2],
+ defaultOutput};
+
+ Object[] actual = match(literal(input),
+ literal(labels[0]), literal(outputs[0]),
+ literal(labels[1]), literal(outputs[1]),
+ literal(labels[2]), literal(outputs[2]),
+ literal(defaultOutput)
+ ).toArray();
+
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testMatchWithStops() throws Exception {
+ String input = "input";
+ String[] labels = new String[] {"a", "b", "c"};
+ String[] outputs = new String[] {"1", "2", "3"};
+ String defaultOutput = "0";
+
+ Object[] expected = new Object[] {"match", input,
+ labels[0], outputs[0],
+ labels[1], outputs[1],
+ labels[2], outputs[2],
+ defaultOutput};
+
+ Object[] actual = match(literal(input), literal(defaultOutput),
+ stop(labels[0], outputs[0]),
+ stop(labels[1], outputs[1]),
+ stop(labels[2], outputs[2]))
+ .toArray();
- Object[] expected = new Object[] {"match", labelZero, labelOne, labelTwo};
- Object[] actual = match(literal(labelZero), literal(labelOne), literal(labelTwo)).toArray();
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
}
@@ -331,14 +368,14 @@ public class ExpressionTest {
@Test
public void testAt() throws Exception {
- Object[] expected = new Object[] {"at", 3, new Object[] {"one", "two"}};
+ Object[] expected = new Object[] {"at", 3, new Object[] {"literal", new Object[] {"one", "two"}}};
Object[] actual = at(literal(3), literal(new Object[] {"one", "two"})).toArray();
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
}
@Test
public void testAtLiteral() throws Exception {
- Object[] expected = new Object[] {"at", 3, new Object[] {"one", "two"}};
+ Object[] expected = new Object[] {"at", 3, new Object[] {"literal", new Object[] {"one", "two"}}};
Object[] actual = at(3, literal(new Object[] {"one", "two"})).toArray();
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
}
@@ -921,12 +958,13 @@ public class ExpressionTest {
@Test
public void testLinear() throws Exception {
- Object[] stopZero = new Object[] {0, 1};
- Object[] stopOne = new Object[] {1, 2};
- Object[] stopTwo = new Object[] {2, 3};
- Object[] expected = new Object[] {"interpolate", new Object[] {"linear"}, 12, stopZero, stopOne, stopTwo};
- Object[] actual = interpolate(linear(), literal(12),
- literal(stopZero), literal(stopOne), literal(stopTwo)).toArray();
+ Object[] expected = new Object[] {"interpolate", new Object[] {"linear"}, 12, 0, 1, 1, 2, 2, 3};
+ Object[] actual = interpolate(
+ linear(), literal(12),
+ literal(0), literal(1),
+ literal(1), literal(2),
+ literal(2), literal(3))
+ .toArray();
assertTrue("expression should match", Arrays.deepEquals(expected, actual));
}
@@ -1030,4 +1068,101 @@ public class ExpressionTest {
get(literal("x")), literal(0), literal(100), literal(100), literal(200)).toString();
assertEquals("toString should match", expected, actual);
}
+
+ @Test
+ public void testLiteralArray() throws Exception {
+ Object[] array = new Object[] {1, "text"};
+ Object[] expected = new Object[] {"literal", array};
+ Object[] actual = literal(array).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testLiteralArrayString() throws Exception {
+ Object[] array = new Object[] {1, "text"};
+ String expected = "[\"literal\"], [1, \"text\"]]";
+ String actual = literal(array).toString();
+ assertEquals("literal array should match", expected, actual);
+ }
+
+ @Test
+ public void testLiteralPrimitiveArrayConversion() throws Exception {
+ float[] array = new float[] {0.2f, 0.5f};
+ Object[] expected = new Object[] {"literal", new Object[] {0.2f, 0.5f}};
+ Object[] actual = literal(array).toArray();
+ assertEquals("primitive array should be converted", expected, actual);
+ }
+
+ @Test
+ public void testColorConversion() {
+ Expression greenColor = color(0xFF00FF00);
+ Object[] expected = new Object[] {"to-color", "rgba(0, 255, 0, 255)"};
+ assertTrue("expression should match", Arrays.deepEquals(expected, greenColor.toArray()));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testThrowIllegalArgumentExceptionForPropertyValueLiteral() {
+ Expression expression = interpolate(exponential(1f), zoom(),
+ stop(17f, lineOpacity(1f)),
+ stop(16.5f, lineOpacity(0.5f)),
+ stop(16f, lineOpacity(0f))
+ );
+ expression.toArray();
+ }
+
+ @Test
+ public void testRound() {
+ Object[] expected = new Object[] {"round", 2.2f};
+ Object[] actual = round(2.2f).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testRoundLiteral() {
+ Object[] expected = new Object[] {"round", 2.2f};
+ Object[] actual = round(literal(2.2f)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testAbs() {
+ Object[] expected = new Object[] {"abs", -2.2f};
+ Object[] actual = abs(-2.2f).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testAbsLiteral() {
+ Object[] expected = new Object[] {"abs", -2.2f};
+ Object[] actual = abs(literal(-2.2f)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testCeil() {
+ Object[] expected = new Object[] {"ceil", 2.2f};
+ Object[] actual = ceil(2.2f).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testCeilLiteral() {
+ Object[] expected = new Object[] {"ceil", 2.2f};
+ Object[] actual = ceil(literal(2.2f)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testFloor() {
+ Object[] expected = new Object[] {"floor", 2.2f};
+ Object[] actual = floor(2.2f).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
+
+ @Test
+ public void testFloorLiteral() {
+ Object[] expected = new Object[] {"floor", 2.2f};
+ Object[] actual = floor(literal(2.2f)).toArray();
+ assertTrue("expression should match", Arrays.deepEquals(expected, actual));
+ }
} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/layers/FilterTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/layers/FilterTest.java
deleted file mode 100644
index 933bf05b39..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/layers/FilterTest.java
+++ /dev/null
@@ -1,102 +0,0 @@
-package com.mapbox.mapboxsdk.style.layers;
-
-import org.junit.Test;
-
-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"});
- }
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/layers/FunctionTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/layers/FunctionTest.java
deleted file mode 100644
index bac1154d62..0000000000
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/style/layers/FunctionTest.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.mapbox.mapboxsdk.style.layers;
-
-import com.mapbox.mapboxsdk.style.functions.Function;
-
-import org.junit.Test;
-
-import static com.mapbox.mapboxsdk.style.functions.Function.zoom;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.interval;
-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<Float, Float> zoomF = zoom(interval(
- 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")
- );
- }
-
-}
diff --git a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/telemetry/HttpTransportTest.java b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/telemetry/HttpTransportTest.java
index 94a6dc2194..519124e1eb 100644
--- a/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/telemetry/HttpTransportTest.java
+++ b/platform/android/MapboxGLAndroidSDK/src/test/java/com/mapbox/mapboxsdk/telemetry/HttpTransportTest.java
@@ -1,8 +1,8 @@
package com.mapbox.mapboxsdk.telemetry;
-import org.junit.Test;
+import com.mapbox.android.telemetry.TelemetryUtils;
-import okhttp3.internal.Util;
+import org.junit.Test;
import static junit.framework.Assert.assertEquals;
@@ -15,6 +15,6 @@ public class HttpTransportTest {
final String asciiVersion = "Sveriges Fj?ll/1.0/1 MapboxEventsAndroid/4.0.0-SNAPSHOT";
assertEquals("asciiVersion and swedishUserAgent should match", asciiVersion,
- Util.toHumanReadableAscii(swedishUserAgent));
+ TelemetryUtils.toHumanReadableAscii(swedishUserAgent));
}
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
index 6707527bf2..edf860a946 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
+++ b/platform/android/MapboxGLAndroidSDKTestApp/build.gradle
@@ -8,7 +8,7 @@ android {
applicationId "com.mapbox.mapboxsdk.testapp"
minSdkVersion androidVersions.minSdkVersion
targetSdkVersion androidVersions.targetSdkVersion
- versionCode 12
+ versionCode 13
versionName "6.0.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
@@ -39,7 +39,7 @@ android {
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
release {
- minifyEnabled false
+ minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
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
deleted file mode 100644
index 38d5297291..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/maps/MapViewUtils.java
+++ /dev/null
@@ -1,33 +0,0 @@
-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
index b4bc118129..38fd8491a8 100644
--- 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
@@ -162,16 +162,6 @@ public class MapboxMapTest extends BaseActivityTest {
}
//
- // TrackingSettings
- //
-
- @Test
- public void testTrackingSettings() {
- validateTestSetup();
- assertNotNull("TrackingSettings should not be null", mapboxMap.getTrackingSettings());
- }
-
- //
// InfoWindow
//
@@ -204,30 +194,6 @@ public class MapboxMapTest extends BaseActivityTest {
}
//
- // Location
- //
-
- @Test
- @Ignore /* disabled due to enabling permissions during test #7177 */
- public void testMyLocationEnabled() {
- validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, 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() {
- validateTestSetup();
- onView(withId(R.id.mapView)).perform(new MapboxMapAction((uiController, view) -> {
- mapboxMap.setMyLocationEnabled(false);
- assertFalse("MyLocationEnabled should be false", mapboxMap.isMyLocationEnabled());
- }));
- }
-
- //
// setters/getters interfaces
//
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
deleted file mode 100644
index 883e76653d..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/camera/CameraInternalApiTest.java
+++ /dev/null
@@ -1,157 +0,0 @@
-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.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.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
-import com.mapbox.mapboxsdk.testapp.utils.TestConstants;
-
-import org.hamcrest.Matcher;
-import org.junit.After;
-import org.junit.Ignore;
-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 extends BaseActivityTest {
-
- @Override
- protected Class getActivityClass() {
- return EspressoTestActivity.class;
- }
-
- @Test
- @Ignore
- public void testBearing() {
- validateTestSetup();
-
- 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
- @Ignore
- public void testTilt() {
- validateTestSetup();
-
- 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
- @Ignore
- public void testLatLng() {
- validateTestSetup();
-
- 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));
- }
- }
-}
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
deleted file mode 100644
index cf58ba50a6..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/maps/widgets/MyLocationViewTest.java
+++ /dev/null
@@ -1,229 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.maps.widgets;
-
-import android.annotation.SuppressLint;
-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.UiController;
-import android.support.test.espresso.ViewAction;
-import android.view.View;
-
-import com.mapbox.mapboxsdk.Mapbox;
-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.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.widgets.MyLocationView;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
-import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
-
-import org.hamcrest.Description;
-import org.hamcrest.Matcher;
-import org.hamcrest.TypeSafeMatcher;
-import org.junit.Ignore;
-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 extends BaseActivityTest {
-
- @Override
- protected Class getActivityClass() {
- return EspressoTestActivity.class;
- }
-
- @Test
- @Ignore // requires runtime permissions, disabled for CI
- public void testEnabled() {
- validateTestSetup();
- 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() {
- validateTestSetup();
- 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)));
- }
-
- 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();
- }
-
- @SuppressLint("MissingPermission")
- @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(Mapbox.getLocationEngine().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/BackgroundLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/BackgroundLayerTest.java
index 0e4cf6a8ca..2d16291832 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
@@ -3,31 +3,18 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
import timber.log.Timber;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
-import com.mapbox.mapboxsdk.style.functions.CameraFunction;
-import com.mapbox.mapboxsdk.style.functions.SourceFunction;
-import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.BackgroundLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
import static org.junit.Assert.*;
import static com.mapbox.mapboxsdk.style.layers.Property.*;
@@ -51,11 +38,8 @@ public class BackgroundLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- layer = mapboxMap.getLayerAs("background");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ layer = mapboxMap.getLayerAs("background");
});
}
@@ -64,18 +48,15 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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);
});
}
@@ -84,16 +65,13 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setBackgroundColorTransition(options);
- assertEquals(layer.getBackgroundColorTransition(), options);
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setBackgroundColorTransition(options);
+ assertEquals(layer.getBackgroundColorTransition(), options);
});
}
@@ -102,47 +80,12 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // 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 testBackgroundColorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("background-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- backgroundColor(
- zoom(
- exponential(
- stop(2, backgroundColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getBackgroundColor());
- assertNotNull(layer.getBackgroundColor().getFunction());
- assertEquals(CameraFunction.class, layer.getBackgroundColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getBackgroundColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getBackgroundColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getBackgroundColor().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(backgroundColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getBackgroundColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -151,15 +94,12 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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);
});
}
@@ -168,16 +108,13 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-patternTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setBackgroundPatternTransition(options);
- assertEquals(layer.getBackgroundPatternTransition(), options);
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setBackgroundPatternTransition(options);
+ assertEquals(layer.getBackgroundPatternTransition(), options);
});
}
@@ -186,46 +123,12 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(backgroundPattern("pedestrian-polygon"));
- assertEquals((String) layer.getBackgroundPattern().getValue(), (String) "pedestrian-polygon");
- }
- });
- }
-
- @Test
- public void testBackgroundPatternAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("background-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- backgroundPattern(
- zoom(
- interval(
- stop(2, backgroundPattern("pedestrian-polygon"))
- )
- )
- )
- );
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Verify
- assertNotNull(layer.getBackgroundPattern());
- assertNotNull(layer.getBackgroundPattern().getFunction());
- assertEquals(CameraFunction.class, layer.getBackgroundPattern().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getBackgroundPattern().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getBackgroundPattern().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(backgroundPattern("pedestrian-polygon"));
+ assertEquals((String) layer.getBackgroundPattern().getValue(), (String) "pedestrian-polygon");
});
}
@@ -234,16 +137,13 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setBackgroundOpacityTransition(options);
- assertEquals(layer.getBackgroundOpacityTransition(), options);
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setBackgroundOpacityTransition(options);
+ assertEquals(layer.getBackgroundOpacityTransition(), options);
});
}
@@ -252,48 +152,12 @@ public class BackgroundLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("background-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(backgroundOpacity(0.3f));
- assertEquals((Float) layer.getBackgroundOpacity().getValue(), (Float) 0.3f);
- }
- });
- }
-
- @Test
- public void testBackgroundOpacityAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("background-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- backgroundOpacity(
- zoom(
- exponential(
- stop(2, backgroundOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Verify
- assertNotNull(layer.getBackgroundOpacity());
- assertNotNull(layer.getBackgroundOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getBackgroundOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getBackgroundOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getBackgroundOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getBackgroundOpacity().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(backgroundOpacity(0.3f));
+ assertEquals((Float) layer.getBackgroundOpacity().getValue(), (Float) 0.3f);
});
}
-
-}
+} \ No newline at end of file
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 559e446307..a851fde6dd 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
@@ -3,31 +3,18 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
import timber.log.Timber;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
-import com.mapbox.mapboxsdk.style.functions.CameraFunction;
-import com.mapbox.mapboxsdk.style.functions.SourceFunction;
-import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
import static org.junit.Assert.*;
import static com.mapbox.mapboxsdk.style.layers.Property.*;
@@ -51,17 +38,14 @@ public class CircleLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- 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");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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");
}
});
}
@@ -71,18 +55,15 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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);
});
}
@@ -91,237 +72,96 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("SourceLayer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Get initial
- assertEquals(layer.getSourceLayer(), "composite");
-
- // Set
- final String sourceLayer = "test";
- layer.setSourceLayer(sourceLayer);
- assertEquals(layer.getSourceLayer(), sourceLayer);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleRadiusTransition() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-radiusTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleRadiusTransition(options);
- assertEquals(layer.getCircleRadiusTransition(), options);
- }
- });
- }
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
- @Test
- public void testCircleRadiusAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleRadius(0.3f));
- assertEquals((Float) layer.getCircleRadius().getValue(), (Float) 0.3f);
- }
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
});
}
@Test
- public void testCircleRadiusAsCameraFunction() {
+ public void testFilter() {
validateTestSetup();
setupLayer();
- Timber.i("circle-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleRadius(
- zoom(
- exponential(
- stop(2, circleRadius(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleRadius());
- assertNotNull(layer.getCircleRadius().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleRadius().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleRadius().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleRadius().getFunction().getStops()).size());
- }
- });
- }
+ Timber.i("Filter");
+ invoke(mapboxMap, (uiController, mapboxMap1) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleRadiusAsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleRadius(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getCircleRadius());
- assertNotNull(layer.getCircleRadius().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleRadius().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleRadius().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
- }
+ // Get initial
+ assertEquals(layer.getFilter(), null);
+
+ // Set
+ Expression filter = eq(get("undefined"), literal(1.0));
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
});
}
+
+
@Test
- public void testCircleRadiusAsExponentialSourceFunction() {
+ public void testCircleRadiusTransition() {
validateTestSetup();
setupLayer();
- Timber.i("circle-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleRadius(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, circleRadius(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleRadius());
- assertNotNull(layer.getCircleRadius().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleRadius().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleRadius().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
- }
+ Timber.i("circle-radiusTransitionOptions");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleRadiusTransition(options);
+ assertEquals(layer.getCircleRadiusTransition(), options);
});
}
@Test
- public void testCircleRadiusAsCategoricalSourceFunction() {
+ public void testCircleRadiusAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("circle-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleRadius(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, circleRadius(0.3f))
- )
- ).withDefaultValue(circleRadius(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleRadius());
- assertNotNull(layer.getCircleRadius().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleRadius().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleRadius().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getCircleRadius().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getCircleRadius().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getCircleRadius().getFunction()).getDefaultValue().getValue());
- }
- });
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+ // Set and Get
+ layer.setProperties(circleRadius(0.3f));
+ assertEquals((Float) layer.getCircleRadius().getValue(), (Float) 0.3f);
+ });
}
@Test
- public void testCircleRadiusAsCompositeFunction() {
+ public void testCircleRadiusAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("circle-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleRadius(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, circleRadius(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(circleRadius(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleRadius());
- assertNotNull(layer.getCircleRadius().getFunction());
- assertEquals(CompositeFunction.class, layer.getCircleRadius().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleRadius().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleRadius().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getCircleRadius().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleRadius().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ Timber.i("circle-radius-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(circleRadius(expression));
+ assertEquals(layer.getCircleRadius().getExpression(), expression);
});
}
+
@Test
public void testCircleColorTransition() {
validateTestSetup();
setupLayer();
Timber.i("circle-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleColorTransition(options);
- assertEquals(layer.getCircleColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleColorTransition(options);
+ assertEquals(layer.getCircleColorTransition(), options);
});
}
@@ -330,157 +170,42 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getCircleColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleColorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleColor(
- zoom(
- exponential(
- stop(2, circleColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleColor());
- assertNotNull(layer.getCircleColor().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleColor().getFunction().getStops()).size());
- }
+ // 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 testCircleColorAsIdentitySourceFunction() {
+ public void testCircleColorAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("circle-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getCircleColor());
- assertNotNull(layer.getCircleColor().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getCircleColor().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("circle-color-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleColorAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, circleColor(Color.RED))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleColor());
- assertNotNull(layer.getCircleColor().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleColor().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(circleColor(expression));
+ assertEquals(layer.getCircleColor().getExpression(), expression);
});
}
- @Test
- public void testCircleColorAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", circleColor(Color.RED))
- )
- ).withDefaultValue(circleColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleColor());
- assertNotNull(layer.getCircleColor().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getCircleColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getCircleColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getCircleColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getCircleColor().getFunction()).getDefaultValue().getColorInt());
- }
- });
-
- }
@Test
public void testCircleColorAsIntConstant() {
validateTestSetup();
setupLayer();
Timber.i("circle-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleColor(Color.RED));
- assertEquals(layer.getCircleColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleColor(Color.RED));
+ assertEquals(layer.getCircleColorAsInt(), Color.RED);
});
}
@@ -489,16 +214,13 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-blurTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleBlurTransition(options);
- assertEquals(layer.getCircleBlurTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleBlurTransition(options);
+ assertEquals(layer.getCircleBlurTransition(), options);
});
}
@@ -507,398 +229,88 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleBlur(0.3f));
- assertEquals((Float) layer.getCircleBlur().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleBlurAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleBlur(
- zoom(
- exponential(
- stop(2, circleBlur(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleBlur());
- assertNotNull(layer.getCircleBlur().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleBlur().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleBlur().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleBlur().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(circleBlur(0.3f));
+ assertEquals((Float) layer.getCircleBlur().getValue(), (Float) 0.3f);
});
}
@Test
- public void testCircleBlurAsIdentitySourceFunction() {
+ public void testCircleBlurAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("circle-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleBlur(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getCircleBlur());
- assertNotNull(layer.getCircleBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleBlur().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("circle-blur-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleBlurAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleBlur(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, circleBlur(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleBlur());
- assertNotNull(layer.getCircleBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(circleBlur(expression));
+ assertEquals(layer.getCircleBlur().getExpression(), expression);
});
}
- @Test
- public void testCircleBlurAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleBlur(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, circleBlur(0.3f))
- )
- ).withDefaultValue(circleBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleBlur());
- assertNotNull(layer.getCircleBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleBlur().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getCircleBlur().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getCircleBlur().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getCircleBlur().getFunction()).getDefaultValue().getValue());
- }
- });
-
- }
-
- @Test
- public void testCircleBlurAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleBlur(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, circleBlur(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(circleBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleBlur());
- assertNotNull(layer.getCircleBlur().getFunction());
- assertEquals(CompositeFunction.class, layer.getCircleBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleBlur().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getCircleBlur().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleBlur().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testCircleOpacityTransition() {
validateTestSetup();
setupLayer();
Timber.i("circle-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleOpacityTransition(options);
- assertEquals(layer.getCircleOpacityTransition(), options);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleOpacityAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleOpacity(0.3f));
- assertEquals((Float) layer.getCircleOpacity().getValue(), (Float) 0.3f);
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleOpacityTransition(options);
+ assertEquals(layer.getCircleOpacityTransition(), options);
});
}
@Test
- public void testCircleOpacityAsCameraFunction() {
+ public void testCircleOpacityAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("circle-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleOpacity(
- zoom(
- exponential(
- stop(2, circleOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleOpacity());
- assertNotNull(layer.getCircleOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleOpacity().getFunction().getStops()).size());
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleOpacityAsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getCircleOpacity());
- assertNotNull(layer.getCircleOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleOpacity().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
- }
+ // Set and Get
+ layer.setProperties(circleOpacity(0.3f));
+ assertEquals((Float) layer.getCircleOpacity().getValue(), (Float) 0.3f);
});
}
@Test
- public void testCircleOpacityAsExponentialSourceFunction() {
+ public void testCircleOpacityAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("circle-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleOpacity(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, circleOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleOpacity());
- assertNotNull(layer.getCircleOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("circle-opacity-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleOpacityAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleOpacity(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, circleOpacity(0.3f))
- )
- ).withDefaultValue(circleOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleOpacity());
- assertNotNull(layer.getCircleOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleOpacity().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getCircleOpacity().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getCircleOpacity().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getCircleOpacity().getFunction()).getDefaultValue().getValue());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(circleOpacity(expression));
+ assertEquals(layer.getCircleOpacity().getExpression(), expression);
});
-
}
- @Test
- public void testCircleOpacityAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleOpacity(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, circleOpacity(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(circleOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleOpacity());
- assertNotNull(layer.getCircleOpacity().getFunction());
- assertEquals(CompositeFunction.class, layer.getCircleOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleOpacity().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getCircleOpacity().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleOpacity().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testCircleTranslateTransition() {
validateTestSetup();
setupLayer();
Timber.i("circle-translateTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleTranslateTransition(options);
- assertEquals(layer.getCircleTranslateTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleTranslateTransition(options);
+ assertEquals(layer.getCircleTranslateTransition(), options);
});
}
@@ -907,47 +319,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleTranslate(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getCircleTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleTranslateAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleTranslate(
- zoom(
- exponential(
- stop(2, circleTranslate(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleTranslate());
- assertNotNull(layer.getCircleTranslate().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleTranslate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleTranslate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleTranslate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleTranslate().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(circleTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getCircleTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -956,46 +333,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleTranslateAnchor(CIRCLE_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getCircleTranslateAnchor().getValue(), (String) CIRCLE_TRANSLATE_ANCHOR_MAP);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleTranslateAnchorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleTranslateAnchor(
- zoom(
- interval(
- stop(2, circleTranslateAnchor(CIRCLE_TRANSLATE_ANCHOR_MAP))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleTranslateAnchor());
- assertNotNull(layer.getCircleTranslateAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleTranslateAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getCircleTranslateAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getCircleTranslateAnchor().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(circleTranslateAnchor(CIRCLE_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getCircleTranslateAnchor().getValue(), (String) CIRCLE_TRANSLATE_ANCHOR_MAP);
});
}
@@ -1004,46 +347,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-pitch-scale");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circlePitchScale(CIRCLE_PITCH_SCALE_MAP));
- assertEquals((String) layer.getCirclePitchScale().getValue(), (String) CIRCLE_PITCH_SCALE_MAP);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCirclePitchScaleAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-pitch-scale");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circlePitchScale(
- zoom(
- interval(
- stop(2, circlePitchScale(CIRCLE_PITCH_SCALE_MAP))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCirclePitchScale());
- assertNotNull(layer.getCirclePitchScale().getFunction());
- assertEquals(CameraFunction.class, layer.getCirclePitchScale().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getCirclePitchScale().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getCirclePitchScale().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(circlePitchScale(CIRCLE_PITCH_SCALE_MAP));
+ assertEquals((String) layer.getCirclePitchScale().getValue(), (String) CIRCLE_PITCH_SCALE_MAP);
});
}
@@ -1052,46 +361,12 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-pitch-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circlePitchAlignment(CIRCLE_PITCH_ALIGNMENT_MAP));
- assertEquals((String) layer.getCirclePitchAlignment().getValue(), (String) CIRCLE_PITCH_ALIGNMENT_MAP);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCirclePitchAlignmentAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-pitch-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circlePitchAlignment(
- zoom(
- interval(
- stop(2, circlePitchAlignment(CIRCLE_PITCH_ALIGNMENT_MAP))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCirclePitchAlignment());
- assertNotNull(layer.getCirclePitchAlignment().getFunction());
- assertEquals(CameraFunction.class, layer.getCirclePitchAlignment().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getCirclePitchAlignment().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getCirclePitchAlignment().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(circlePitchAlignment(CIRCLE_PITCH_ALIGNMENT_MAP));
+ assertEquals((String) layer.getCirclePitchAlignment().getValue(), (String) CIRCLE_PITCH_ALIGNMENT_MAP);
});
}
@@ -1100,216 +375,58 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-widthTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleStrokeWidthTransition(options);
- assertEquals(layer.getCircleStrokeWidthTransition(), options);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleStrokeWidthAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-stroke-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleStrokeWidth(0.3f));
- assertEquals((Float) layer.getCircleStrokeWidth().getValue(), (Float) 0.3f);
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleStrokeWidthTransition(options);
+ assertEquals(layer.getCircleStrokeWidthTransition(), options);
});
}
@Test
- public void testCircleStrokeWidthAsCameraFunction() {
+ public void testCircleStrokeWidthAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeWidth(
- zoom(
- exponential(
- stop(2, circleStrokeWidth(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeWidth());
- assertNotNull(layer.getCircleStrokeWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleStrokeWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleStrokeWidth().getFunction().getStops()).size());
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleStrokeWidthAsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-stroke-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeWidth(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeWidth());
- assertNotNull(layer.getCircleStrokeWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
- }
+ // Set and Get
+ layer.setProperties(circleStrokeWidth(0.3f));
+ assertEquals((Float) layer.getCircleStrokeWidth().getValue(), (Float) 0.3f);
});
}
@Test
- public void testCircleStrokeWidthAsExponentialSourceFunction() {
+ public void testCircleStrokeWidthAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("circle-stroke-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeWidth(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, circleStrokeWidth(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeWidth());
- assertNotNull(layer.getCircleStrokeWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("circle-stroke-width-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleStrokeWidthAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-stroke-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeWidth(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, circleStrokeWidth(0.3f))
- )
- ).withDefaultValue(circleStrokeWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeWidth());
- assertNotNull(layer.getCircleStrokeWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getCircleStrokeWidth().getFunction()).getDefaultValue().getValue());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(circleStrokeWidth(expression));
+ assertEquals(layer.getCircleStrokeWidth().getExpression(), expression);
});
-
}
- @Test
- public void testCircleStrokeWidthAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-stroke-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeWidth(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, circleStrokeWidth(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(circleStrokeWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeWidth());
- assertNotNull(layer.getCircleStrokeWidth().getFunction());
- assertEquals(CompositeFunction.class, layer.getCircleStrokeWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleStrokeWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeWidth().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getCircleStrokeWidth().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleStrokeWidth().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testCircleStrokeColorTransition() {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleStrokeColorTransition(options);
- assertEquals(layer.getCircleStrokeColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleStrokeColorTransition(options);
+ assertEquals(layer.getCircleStrokeColorTransition(), options);
});
}
@@ -1318,157 +435,42 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleStrokeColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getCircleStrokeColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleStrokeColorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-stroke-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeColor(
- zoom(
- exponential(
- stop(2, circleStrokeColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeColor());
- assertNotNull(layer.getCircleStrokeColor().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleStrokeColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleStrokeColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleStrokeColor().getFunction().getStops()).size());
- }
+ // 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 testCircleStrokeColorAsIdentitySourceFunction() {
+ public void testCircleStrokeColorAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("circle-stroke-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeColor());
- assertNotNull(layer.getCircleStrokeColor().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getCircleStrokeColor().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("circle-stroke-color-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleStrokeColorAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-stroke-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, circleStrokeColor(Color.RED))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeColor());
- assertNotNull(layer.getCircleStrokeColor().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeColor().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(circleStrokeColor(expression));
+ assertEquals(layer.getCircleStrokeColor().getExpression(), expression);
});
}
- @Test
- public void testCircleStrokeColorAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-stroke-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", circleStrokeColor(Color.RED))
- )
- ).withDefaultValue(circleStrokeColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeColor());
- assertNotNull(layer.getCircleStrokeColor().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getCircleStrokeColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getCircleStrokeColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getCircleStrokeColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getCircleStrokeColor().getFunction()).getDefaultValue().getColorInt());
- }
- });
-
- }
@Test
public void testCircleStrokeColorAsIntConstant() {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleStrokeColor(Color.RED));
- assertEquals(layer.getCircleStrokeColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(circleStrokeColor(Color.RED));
+ assertEquals(layer.getCircleStrokeColorAsInt(), Color.RED);
});
}
@@ -1477,199 +479,43 @@ public class CircleLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setCircleStrokeOpacityTransition(options);
- assertEquals(layer.getCircleStrokeOpacityTransition(), options);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleStrokeOpacityAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-stroke-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(circleStrokeOpacity(0.3f));
- assertEquals((Float) layer.getCircleStrokeOpacity().getValue(), (Float) 0.3f);
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setCircleStrokeOpacityTransition(options);
+ assertEquals(layer.getCircleStrokeOpacityTransition(), options);
});
}
@Test
- public void testCircleStrokeOpacityAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-stroke-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeOpacity(
- zoom(
- exponential(
- stop(2, circleStrokeOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeOpacity());
- assertNotNull(layer.getCircleStrokeOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getCircleStrokeOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getCircleStrokeOpacity().getFunction().getStops()).size());
- }
- });
- }
-
- @Test
- public void testCircleStrokeOpacityAsIdentitySourceFunction() {
+ public void testCircleStrokeOpacityAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("circle-stroke-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeOpacity());
- assertNotNull(layer.getCircleStrokeOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleStrokeOpacityAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-stroke-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeOpacity(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, circleStrokeOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeOpacity());
- assertNotNull(layer.getCircleStrokeOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
- }
+ // Set and Get
+ layer.setProperties(circleStrokeOpacity(0.3f));
+ assertEquals((Float) layer.getCircleStrokeOpacity().getValue(), (Float) 0.3f);
});
}
@Test
- public void testCircleStrokeOpacityAsCategoricalSourceFunction() {
+ public void testCircleStrokeOpacityAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("circle-stroke-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeOpacity(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, circleStrokeOpacity(0.3f))
- )
- ).withDefaultValue(circleStrokeOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeOpacity());
- assertNotNull(layer.getCircleStrokeOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getCircleStrokeOpacity().getFunction()).getDefaultValue().getValue());
- }
- });
-
- }
+ Timber.i("circle-stroke-opacity-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testCircleStrokeOpacityAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("circle-stroke-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- circleStrokeOpacity(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, circleStrokeOpacity(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(circleStrokeOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getCircleStrokeOpacity());
- assertNotNull(layer.getCircleStrokeOpacity().getFunction());
- assertEquals(CompositeFunction.class, layer.getCircleStrokeOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getCircleStrokeOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getCircleStrokeOpacity().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getCircleStrokeOpacity().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getCircleStrokeOpacity().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(circleStrokeOpacity(expression));
+ assertEquals(layer.getCircleStrokeOpacity().getExpression(), expression);
});
}
-}
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ExpressionTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ExpressionTest.java
new file mode 100644
index 0000000000..c4ff79b053
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/ExpressionTest.java
@@ -0,0 +1,207 @@
+package com.mapbox.mapboxsdk.testapp.style;
+
+import android.graphics.Color;
+import android.support.test.runner.AndroidJUnit4;
+
+import com.mapbox.mapboxsdk.style.expressions.Expression;
+import com.mapbox.mapboxsdk.style.layers.FillLayer;
+import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
+import com.mapbox.mapboxsdk.style.sources.Source;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.IOException;
+
+import timber.log.Timber;
+
+import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.match;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.rgb;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.rgba;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.step;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.string;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.toColor;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom;
+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.fillOutlineColor;
+import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
+import static org.junit.Assert.assertEquals;
+
+@RunWith(AndroidJUnit4.class)
+public class ExpressionTest extends BaseActivityTest {
+
+ private FillLayer layer;
+
+ @Test
+ public void testConstantExpressionConversion() {
+ validateTestSetup();
+ setupStyle();
+ Timber.i("camera function");
+
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ // create color expression
+ Expression inputExpression = rgba(255.0f, 0.0f, 0.0f, 1.0f);
+
+ // set color expression
+ layer.setProperties(
+ fillColor(inputExpression)
+ );
+
+ // get color value
+ int color = layer.getFillColor().getColorInt();
+
+ // compare
+ assertEquals("input expression should match", Color.RED, color);
+ });
+ }
+
+ @Test
+ public void testGetExpressionWrapping() {
+ validateTestSetup();
+ setupStyle();
+ Timber.i("camera function");
+
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ // create get expression
+ Expression inputExpression = get("fill");
+
+ // set get expression
+ layer.setProperties(
+ fillColor(inputExpression)
+ );
+
+ // get actual expression
+ Expression actualExpression = layer.getFillColor().getExpression();
+
+ // create wrapped expected expression
+ Expression expectedExpression = toColor(get("fill"));
+
+ // compare
+ assertEquals("input expression should match", expectedExpression, actualExpression);
+ });
+ }
+
+ @Test
+ public void testCameraFunction() {
+ validateTestSetup();
+ setupStyle();
+ Timber.i("camera function");
+
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ // create camera function expression
+ Expression inputExpression = interpolate(
+ exponential(0.5f), zoom(),
+ stop(1.0f, rgba(255.0f, 0.0f, 0.0f, 1.0f)),
+ stop(5.0f, rgba(0.0f, 0.0f, 255.0f, 1.0f)),
+ stop(10.0f, rgba(0.0f, 255.0f, 0.0f, 1.0f))
+ );
+
+ // set camera function expression
+ layer.setProperties(
+ fillColor(inputExpression)
+ );
+
+ // get camera function expression
+ Expression outputExpression = layer.getFillColor().getExpression();
+
+ // compare
+ assertEquals("input expression should match", inputExpression, outputExpression);
+ });
+ }
+
+ @Test
+ public void testSourceFunction() {
+ validateTestSetup();
+ setupStyle();
+ Timber.i("camera function");
+
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ // create camera function expression
+ Expression inputExpression = toColor(get("fill"));
+
+ // set camera function expression
+ layer.setProperties(
+ fillColor(inputExpression)
+ );
+
+ // get camera function expression
+ Expression outputExpression = layer.getFillColor().getExpression();
+
+ // compare
+ assertEquals("input expression should match", inputExpression, outputExpression);
+ });
+ }
+
+ @Test
+ public void testCompositeFunction() {
+ validateTestSetup();
+ setupStyle();
+ Timber.i("camera function");
+
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ // create camera function expression
+ Expression inputExpression = step(zoom(),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f),
+ stop(7.0f, match(
+ string(get("name")),
+ literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
+ )),
+ stop(8.0f, match(
+ string(get("name")),
+ literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
+ ))
+ );
+
+ // set camera function expression
+ layer.setProperties(
+ fillColor(inputExpression)
+ );
+
+ // get camera function expression
+ Expression outputExpression = layer.getFillColor().getExpression();
+
+ // compare
+ assertEquals("input expression should match", inputExpression, outputExpression);
+ });
+ }
+
+ private void setupStyle() {
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ // Add a source
+ Source source;
+ try {
+ source = new GeoJsonSource("amsterdam-parks-source",
+ ResourceUtils.readRawResource(rule.getActivity(), R.raw.amsterdam));
+ mapboxMap.addSource(source);
+ } catch (IOException ioException) {
+ return;
+ }
+
+ // Add a fill layer
+ mapboxMap.addLayer(layer = new FillLayer("amsterdam-parks-layer", source.getId())
+ .withProperties(
+ fillColor(rgba(0.0f, 0.0f, 0.0f, 0.5f)),
+ fillOutlineColor(rgb(0, 0, 255)),
+ fillAntialias(true)
+ )
+ );
+ });
+ }
+
+ @Override
+ protected Class getActivityClass() {
+ return EspressoTestActivity.class;
+ }
+}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java
index 66c6093537..f22956072d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/FillExtrusionLayerTest.java
@@ -3,31 +3,18 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
import timber.log.Timber;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
-import com.mapbox.mapboxsdk.style.functions.CameraFunction;
-import com.mapbox.mapboxsdk.style.functions.SourceFunction;
-import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
import static org.junit.Assert.*;
import static com.mapbox.mapboxsdk.style.layers.Property.*;
@@ -51,17 +38,14 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Timber.i("Adding layer");
- layer = new FillExtrusionLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- // Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new FillExtrusionLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ // Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
});
}
@@ -71,18 +55,15 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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);
});
}
@@ -91,86 +72,65 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("SourceLayer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Get initial
- assertEquals(layer.getSourceLayer(), "composite");
-
- // Set
- final String sourceLayer = "test";
- layer.setSourceLayer(sourceLayer);
- assertEquals(layer.getSourceLayer(), sourceLayer);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
});
}
@Test
- public void testFillExtrusionOpacityTransition() {
+ public void testFilter() {
validateTestSetup();
setupLayer();
- Timber.i("fill-extrusion-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillExtrusionOpacityTransition(options);
- assertEquals(layer.getFillExtrusionOpacityTransition(), options);
- }
+ Timber.i("Filter");
+ invoke(mapboxMap, (uiController, mapboxMap1) -> {
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getFilter(), null);
+
+ // Set
+ Expression filter = eq(get("undefined"), literal(1.0));
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
});
}
+
+
@Test
- public void testFillExtrusionOpacityAsConstant() {
+ public void testFillExtrusionOpacityTransition() {
validateTestSetup();
setupLayer();
- Timber.i("fill-extrusion-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionOpacity(0.3f));
- assertEquals((Float) layer.getFillExtrusionOpacity().getValue(), (Float) 0.3f);
- }
+ Timber.i("fill-extrusion-opacityTransitionOptions");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionOpacityTransition(options);
+ assertEquals(layer.getFillExtrusionOpacityTransition(), options);
});
}
@Test
- public void testFillExtrusionOpacityAsCameraFunction() {
+ public void testFillExtrusionOpacityAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionOpacity(
- zoom(
- exponential(
- stop(2, fillExtrusionOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionOpacity());
- assertNotNull(layer.getFillExtrusionOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getFillExtrusionOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillExtrusionOpacity().getFunction().getStops()).size());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillExtrusionOpacity(0.3f));
+ assertEquals((Float) layer.getFillExtrusionOpacity().getValue(), (Float) 0.3f);
});
}
@@ -179,16 +139,13 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillExtrusionColorTransition(options);
- assertEquals(layer.getFillExtrusionColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionColorTransition(options);
+ assertEquals(layer.getFillExtrusionColorTransition(), options);
});
}
@@ -197,157 +154,42 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getFillExtrusionColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillExtrusionColorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-extrusion-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionColor(
- zoom(
- exponential(
- stop(2, fillExtrusionColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionColor());
- assertNotNull(layer.getFillExtrusionColor().getFunction());
- assertEquals(CameraFunction.class, layer.getFillExtrusionColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillExtrusionColor().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(fillExtrusionColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getFillExtrusionColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@Test
- public void testFillExtrusionColorAsIdentitySourceFunction() {
+ public void testFillExtrusionColorAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("fill-extrusion-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionColor());
- assertNotNull(layer.getFillExtrusionColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getFillExtrusionColor().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("fill-extrusion-color-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillExtrusionColorAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-extrusion-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, fillExtrusionColor(Color.RED))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionColor());
- assertNotNull(layer.getFillExtrusionColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionColor().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(fillExtrusionColor(expression));
+ assertEquals(layer.getFillExtrusionColor().getExpression(), expression);
});
}
- @Test
- public void testFillExtrusionColorAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-extrusion-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", fillExtrusionColor(Color.RED))
- )
- ).withDefaultValue(fillExtrusionColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionColor());
- assertNotNull(layer.getFillExtrusionColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getFillExtrusionColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getFillExtrusionColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getFillExtrusionColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getFillExtrusionColor().getFunction()).getDefaultValue().getColorInt());
- }
- });
-
- }
@Test
public void testFillExtrusionColorAsIntConstant() {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionColor(Color.RED));
- assertEquals(layer.getFillExtrusionColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillExtrusionColor(Color.RED));
+ assertEquals(layer.getFillExtrusionColorAsInt(), Color.RED);
});
}
@@ -356,16 +198,13 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-translateTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillExtrusionTranslateTransition(options);
- assertEquals(layer.getFillExtrusionTranslateTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionTranslateTransition(options);
+ assertEquals(layer.getFillExtrusionTranslateTransition(), options);
});
}
@@ -374,47 +213,12 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionTranslate(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getFillExtrusionTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillExtrusionTranslateAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-extrusion-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionTranslate(
- zoom(
- exponential(
- stop(2, fillExtrusionTranslate(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionTranslate());
- assertNotNull(layer.getFillExtrusionTranslate().getFunction());
- assertEquals(CameraFunction.class, layer.getFillExtrusionTranslate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionTranslate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionTranslate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillExtrusionTranslate().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(fillExtrusionTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getFillExtrusionTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -423,46 +227,12 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionTranslateAnchor(FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getFillExtrusionTranslateAnchor().getValue(), (String) FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillExtrusionTranslateAnchorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-extrusion-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionTranslateAnchor(
- zoom(
- interval(
- stop(2, fillExtrusionTranslateAnchor(FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionTranslateAnchor());
- assertNotNull(layer.getFillExtrusionTranslateAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getFillExtrusionTranslateAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getFillExtrusionTranslateAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getFillExtrusionTranslateAnchor().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(fillExtrusionTranslateAnchor(FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getFillExtrusionTranslateAnchor().getValue(), (String) FILL_EXTRUSION_TRANSLATE_ANCHOR_MAP);
});
}
@@ -471,16 +241,13 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-patternTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillExtrusionPatternTransition(options);
- assertEquals(layer.getFillExtrusionPatternTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionPatternTransition(options);
+ assertEquals(layer.getFillExtrusionPatternTransition(), options);
});
}
@@ -489,46 +256,12 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionPattern("pedestrian-polygon"));
- assertEquals((String) layer.getFillExtrusionPattern().getValue(), (String) "pedestrian-polygon");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillExtrusionPatternAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-extrusion-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionPattern(
- zoom(
- interval(
- stop(2, fillExtrusionPattern("pedestrian-polygon"))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionPattern());
- assertNotNull(layer.getFillExtrusionPattern().getFunction());
- assertEquals(CameraFunction.class, layer.getFillExtrusionPattern().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getFillExtrusionPattern().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getFillExtrusionPattern().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(fillExtrusionPattern("pedestrian-polygon"));
+ assertEquals((String) layer.getFillExtrusionPattern().getValue(), (String) "pedestrian-polygon");
});
}
@@ -537,16 +270,13 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-heightTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillExtrusionHeightTransition(options);
- assertEquals(layer.getFillExtrusionHeightTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionHeightTransition(options);
+ assertEquals(layer.getFillExtrusionHeightTransition(), options);
});
}
@@ -555,198 +285,43 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionHeight(0.3f));
- assertEquals((Float) layer.getFillExtrusionHeight().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillExtrusionHeightAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-extrusion-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionHeight(
- zoom(
- exponential(
- stop(2, fillExtrusionHeight(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionHeight());
- assertNotNull(layer.getFillExtrusionHeight().getFunction());
- assertEquals(CameraFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionHeight().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillExtrusionHeight().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(fillExtrusionHeight(0.3f));
+ assertEquals((Float) layer.getFillExtrusionHeight().getValue(), (Float) 0.3f);
});
}
@Test
- public void testFillExtrusionHeightAsIdentitySourceFunction() {
+ public void testFillExtrusionHeightAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("fill-extrusion-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionHeight(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionHeight());
- assertNotNull(layer.getFillExtrusionHeight().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("fill-extrusion-height-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillExtrusionHeightAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-extrusion-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionHeight(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, fillExtrusionHeight(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionHeight());
- assertNotNull(layer.getFillExtrusionHeight().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
- }
- });
- }
-
- @Test
- public void testFillExtrusionHeightAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-extrusion-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionHeight(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, fillExtrusionHeight(0.3f))
- )
- ).withDefaultValue(fillExtrusionHeight(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionHeight());
- assertNotNull(layer.getFillExtrusionHeight().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getFillExtrusionHeight().getFunction()).getDefaultValue().getValue());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(fillExtrusionHeight(expression));
+ assertEquals(layer.getFillExtrusionHeight().getExpression(), expression);
});
-
}
- @Test
- public void testFillExtrusionHeightAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-extrusion-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionHeight(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, fillExtrusionHeight(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(fillExtrusionHeight(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionHeight());
- assertNotNull(layer.getFillExtrusionHeight().getFunction());
- assertEquals(CompositeFunction.class, layer.getFillExtrusionHeight().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getFillExtrusionHeight().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionHeight().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getFillExtrusionHeight().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getFillExtrusionHeight().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testFillExtrusionBaseTransition() {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-baseTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillExtrusionBaseTransition(options);
- assertEquals(layer.getFillExtrusionBaseTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillExtrusionBaseTransition(options);
+ assertEquals(layer.getFillExtrusionBaseTransition(), options);
});
}
@@ -755,181 +330,28 @@ public class FillExtrusionLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-extrusion-base");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillExtrusionBase(0.3f));
- assertEquals((Float) layer.getFillExtrusionBase().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillExtrusionBaseAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-extrusion-base");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionBase(
- zoom(
- exponential(
- stop(2, fillExtrusionBase(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionBase());
- assertNotNull(layer.getFillExtrusionBase().getFunction());
- assertEquals(CameraFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillExtrusionBase().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillExtrusionBase().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(fillExtrusionBase(0.3f));
+ assertEquals((Float) layer.getFillExtrusionBase().getValue(), (Float) 0.3f);
});
}
@Test
- public void testFillExtrusionBaseAsIdentitySourceFunction() {
+ public void testFillExtrusionBaseAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("fill-extrusion-base");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionBase(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionBase());
- assertNotNull(layer.getFillExtrusionBase().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionBase().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("fill-extrusion-base-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillExtrusionBaseAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-extrusion-base");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionBase(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, fillExtrusionBase(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionBase());
- assertNotNull(layer.getFillExtrusionBase().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionBase().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
- }
- });
- }
-
- @Test
- public void testFillExtrusionBaseAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-extrusion-base");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionBase(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, fillExtrusionBase(0.3f))
- )
- ).withDefaultValue(fillExtrusionBase(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionBase());
- assertNotNull(layer.getFillExtrusionBase().getFunction());
- assertEquals(SourceFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillExtrusionBase().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getFillExtrusionBase().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getFillExtrusionBase().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getFillExtrusionBase().getFunction()).getDefaultValue().getValue());
- }
- });
-
- }
-
- @Test
- public void testFillExtrusionBaseAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-extrusion-base");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillExtrusionBase(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, fillExtrusionBase(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(fillExtrusionBase(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillExtrusionBase());
- assertNotNull(layer.getFillExtrusionBase().getFunction());
- assertEquals(CompositeFunction.class, layer.getFillExtrusionBase().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getFillExtrusionBase().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillExtrusionBase().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getFillExtrusionBase().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getFillExtrusionBase().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(fillExtrusionBase(expression));
+ assertEquals(layer.getFillExtrusionBase().getExpression(), expression);
});
}
-}
+} \ No newline at end of file
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 939bcb6892..bdbd8958d2 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
@@ -3,31 +3,18 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
import timber.log.Timber;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
-import com.mapbox.mapboxsdk.style.functions.CameraFunction;
-import com.mapbox.mapboxsdk.style.functions.SourceFunction;
-import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
import static org.junit.Assert.*;
import static com.mapbox.mapboxsdk.style.layers.Property.*;
@@ -51,17 +38,14 @@ public class FillLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- 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");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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");
}
});
}
@@ -71,18 +55,15 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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);
});
}
@@ -91,67 +72,50 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("SourceLayer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Get initial
- assertEquals(layer.getSourceLayer(), "composite");
-
- // Set
- final String sourceLayer = "test";
- layer.setSourceLayer(sourceLayer);
- assertEquals(layer.getSourceLayer(), sourceLayer);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
});
}
@Test
- public void testFillAntialiasAsConstant() {
+ public void testFilter() {
validateTestSetup();
setupLayer();
- Timber.i("fill-antialias");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillAntialias(true));
- assertEquals((Boolean) layer.getFillAntialias().getValue(), (Boolean) true);
- }
+ Timber.i("Filter");
+ invoke(mapboxMap, (uiController, mapboxMap1) -> {
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getFilter(), null);
+
+ // Set
+ Expression filter = eq(get("undefined"), literal(1.0));
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
});
}
+
+
@Test
- public void testFillAntialiasAsCameraFunction() {
+ public void testFillAntialiasAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("fill-antialias");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillAntialias(
- zoom(
- interval(
- stop(2, fillAntialias(true))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillAntialias());
- assertNotNull(layer.getFillAntialias().getFunction());
- assertEquals(CameraFunction.class, layer.getFillAntialias().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getFillAntialias().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getFillAntialias().getFunction().getStops()).size());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillAntialias(true));
+ assertEquals((Boolean) layer.getFillAntialias().getValue(), (Boolean) true);
});
}
@@ -160,216 +124,58 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillOpacityTransition(options);
- assertEquals(layer.getFillOpacityTransition(), options);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillOpacityAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillOpacity(0.3f));
- assertEquals((Float) layer.getFillOpacity().getValue(), (Float) 0.3f);
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillOpacityTransition(options);
+ assertEquals(layer.getFillOpacityTransition(), options);
});
}
@Test
- public void testFillOpacityAsCameraFunction() {
+ public void testFillOpacityAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("fill-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOpacity(
- zoom(
- exponential(
- stop(2, fillOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillOpacity());
- assertNotNull(layer.getFillOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getFillOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillOpacity().getFunction().getStops()).size());
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillOpacityAsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getFillOpacity());
- assertNotNull(layer.getFillOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getFillOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOpacity().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
- }
+ // Set and Get
+ layer.setProperties(fillOpacity(0.3f));
+ assertEquals((Float) layer.getFillOpacity().getValue(), (Float) 0.3f);
});
}
@Test
- public void testFillOpacityAsExponentialSourceFunction() {
+ public void testFillOpacityAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("fill-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOpacity(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, fillOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillOpacity());
- assertNotNull(layer.getFillOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getFillOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("fill-opacity-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillOpacityAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOpacity(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, fillOpacity(0.3f))
- )
- ).withDefaultValue(fillOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillOpacity());
- assertNotNull(layer.getFillOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getFillOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOpacity().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getFillOpacity().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getFillOpacity().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getFillOpacity().getFunction()).getDefaultValue().getValue());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(fillOpacity(expression));
+ assertEquals(layer.getFillOpacity().getExpression(), expression);
});
-
}
- @Test
- public void testFillOpacityAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOpacity(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, fillOpacity(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(fillOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillOpacity());
- assertNotNull(layer.getFillOpacity().getFunction());
- assertEquals(CompositeFunction.class, layer.getFillOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getFillOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillOpacity().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getFillOpacity().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getFillOpacity().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testFillColorTransition() {
validateTestSetup();
setupLayer();
Timber.i("fill-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillColorTransition(options);
- assertEquals(layer.getFillColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillColorTransition(options);
+ assertEquals(layer.getFillColorTransition(), options);
});
}
@@ -378,157 +184,42 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getFillColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillColorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillColor(
- zoom(
- exponential(
- stop(2, fillColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillColor());
- assertNotNull(layer.getFillColor().getFunction());
- assertEquals(CameraFunction.class, layer.getFillColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillColor().getFunction().getStops()).size());
- }
+ // 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 testFillColorAsIdentitySourceFunction() {
+ public void testFillColorAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("fill-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getFillColor());
- assertNotNull(layer.getFillColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getFillColor().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("fill-color-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillColorAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, fillColor(Color.RED))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillColor());
- assertNotNull(layer.getFillColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillColor().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(fillColor(expression));
+ assertEquals(layer.getFillColor().getExpression(), expression);
});
}
- @Test
- public void testFillColorAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", fillColor(Color.RED))
- )
- ).withDefaultValue(fillColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillColor());
- assertNotNull(layer.getFillColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getFillColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getFillColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getFillColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getFillColor().getFunction()).getDefaultValue().getColorInt());
- }
- });
-
- }
@Test
public void testFillColorAsIntConstant() {
validateTestSetup();
setupLayer();
Timber.i("fill-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillColor(Color.RED));
- assertEquals(layer.getFillColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillColor(Color.RED));
+ assertEquals(layer.getFillColorAsInt(), Color.RED);
});
}
@@ -537,16 +228,13 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-outline-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillOutlineColorTransition(options);
- assertEquals(layer.getFillOutlineColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillOutlineColorTransition(options);
+ assertEquals(layer.getFillOutlineColorTransition(), options);
});
}
@@ -555,157 +243,42 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-outline-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillOutlineColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getFillOutlineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillOutlineColorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-outline-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOutlineColor(
- zoom(
- exponential(
- stop(2, fillOutlineColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillOutlineColor());
- assertNotNull(layer.getFillOutlineColor().getFunction());
- assertEquals(CameraFunction.class, layer.getFillOutlineColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillOutlineColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillOutlineColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillOutlineColor().getFunction().getStops()).size());
- }
+ // 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 testFillOutlineColorAsIdentitySourceFunction() {
+ public void testFillOutlineColorAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("fill-outline-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOutlineColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getFillOutlineColor());
- assertNotNull(layer.getFillOutlineColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillOutlineColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOutlineColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getFillOutlineColor().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("fill-outline-color-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillOutlineColorAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-outline-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOutlineColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, fillOutlineColor(Color.RED))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillOutlineColor());
- assertNotNull(layer.getFillOutlineColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillOutlineColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOutlineColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getFillOutlineColor().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(fillOutlineColor(expression));
+ assertEquals(layer.getFillOutlineColor().getExpression(), expression);
});
}
- @Test
- public void testFillOutlineColorAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-outline-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillOutlineColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", fillOutlineColor(Color.RED))
- )
- ).withDefaultValue(fillOutlineColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getFillOutlineColor());
- assertNotNull(layer.getFillOutlineColor().getFunction());
- assertEquals(SourceFunction.class, layer.getFillOutlineColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getFillOutlineColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getFillOutlineColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getFillOutlineColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getFillOutlineColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getFillOutlineColor().getFunction()).getDefaultValue().getColorInt());
- }
- });
-
- }
@Test
public void testFillOutlineColorAsIntConstant() {
validateTestSetup();
setupLayer();
Timber.i("fill-outline-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillOutlineColor(Color.RED));
- assertEquals(layer.getFillOutlineColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(fillOutlineColor(Color.RED));
+ assertEquals(layer.getFillOutlineColorAsInt(), Color.RED);
});
}
@@ -714,16 +287,13 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-translateTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillTranslateTransition(options);
- assertEquals(layer.getFillTranslateTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillTranslateTransition(options);
+ assertEquals(layer.getFillTranslateTransition(), options);
});
}
@@ -732,47 +302,12 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillTranslate(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getFillTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillTranslateAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillTranslate(
- zoom(
- exponential(
- stop(2, fillTranslate(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillTranslate());
- assertNotNull(layer.getFillTranslate().getFunction());
- assertEquals(CameraFunction.class, layer.getFillTranslate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getFillTranslate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getFillTranslate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getFillTranslate().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(fillTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getFillTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -781,46 +316,12 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getFillTranslateAnchor().getValue(), (String) FILL_TRANSLATE_ANCHOR_MAP);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillTranslateAnchorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillTranslateAnchor(
- zoom(
- interval(
- stop(2, fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillTranslateAnchor());
- assertNotNull(layer.getFillTranslateAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getFillTranslateAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getFillTranslateAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getFillTranslateAnchor().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(fillTranslateAnchor(FILL_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getFillTranslateAnchor().getValue(), (String) FILL_TRANSLATE_ANCHOR_MAP);
});
}
@@ -829,16 +330,13 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-patternTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setFillPatternTransition(options);
- assertEquals(layer.getFillPatternTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setFillPatternTransition(options);
+ assertEquals(layer.getFillPatternTransition(), options);
});
}
@@ -847,47 +345,12 @@ public class FillLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("fill-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(fillPattern("pedestrian-polygon"));
- assertEquals((String) layer.getFillPattern().getValue(), (String) "pedestrian-polygon");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testFillPatternAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("fill-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- fillPattern(
- zoom(
- interval(
- stop(2, fillPattern("pedestrian-polygon"))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getFillPattern());
- assertNotNull(layer.getFillPattern().getFunction());
- assertEquals(CameraFunction.class, layer.getFillPattern().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getFillPattern().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getFillPattern().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(fillPattern("pedestrian-polygon"));
+ assertEquals((String) layer.getFillPattern().getValue(), (String) "pedestrian-polygon");
});
}
-
-}
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HeatmapLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HeatmapLayerTest.java
index 364c8d2679..549f309e4f 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HeatmapLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HeatmapLayerTest.java
@@ -3,31 +3,18 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
import timber.log.Timber;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
-import com.mapbox.mapboxsdk.style.functions.CameraFunction;
-import com.mapbox.mapboxsdk.style.functions.SourceFunction;
-import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.HeatmapLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
import static org.junit.Assert.*;
import static com.mapbox.mapboxsdk.style.layers.Property.*;
@@ -51,17 +38,14 @@ public class HeatmapLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Timber.i("Adding layer");
- layer = new HeatmapLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- // Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new HeatmapLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ // Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
});
}
@@ -71,18 +55,15 @@ public class HeatmapLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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);
});
}
@@ -91,419 +72,126 @@ public class HeatmapLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("SourceLayer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Get initial
- assertEquals(layer.getSourceLayer(), "composite");
-
- // Set
- final String sourceLayer = "test";
- layer.setSourceLayer(sourceLayer);
- assertEquals(layer.getSourceLayer(), sourceLayer);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testHeatmapRadiusTransition() {
- validateTestSetup();
- setupLayer();
- Timber.i("heatmap-radiusTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setHeatmapRadiusTransition(options);
- assertEquals(layer.getHeatmapRadiusTransition(), options);
- }
- });
- }
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
- @Test
- public void testHeatmapRadiusAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("heatmap-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(heatmapRadius(0.3f));
- assertEquals((Float) layer.getHeatmapRadius().getValue(), (Float) 0.3f);
- }
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
});
}
@Test
- public void testHeatmapRadiusAsCameraFunction() {
+ public void testFilter() {
validateTestSetup();
setupLayer();
- Timber.i("heatmap-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- heatmapRadius(
- zoom(
- exponential(
- stop(2, heatmapRadius(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getHeatmapRadius());
- assertNotNull(layer.getHeatmapRadius().getFunction());
- assertEquals(CameraFunction.class, layer.getHeatmapRadius().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getHeatmapRadius().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getHeatmapRadius().getFunction().getStops()).size());
- }
- });
- }
+ Timber.i("Filter");
+ invoke(mapboxMap, (uiController, mapboxMap1) -> {
+ assertNotNull(layer);
- @Test
- public void testHeatmapRadiusAsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("heatmap-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- heatmapRadius(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getHeatmapRadius());
- assertNotNull(layer.getHeatmapRadius().getFunction());
- assertEquals(SourceFunction.class, layer.getHeatmapRadius().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapRadius().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass());
- }
- });
- }
+ // Get initial
+ assertEquals(layer.getFilter(), null);
- @Test
- public void testHeatmapRadiusAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("heatmap-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- heatmapRadius(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, heatmapRadius(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getHeatmapRadius());
- assertNotNull(layer.getHeatmapRadius().getFunction());
- assertEquals(SourceFunction.class, layer.getHeatmapRadius().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapRadius().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass());
- }
+ // Set
+ Expression filter = eq(get("undefined"), literal(1.0));
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
});
}
- @Test
- public void testHeatmapRadiusAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("heatmap-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- heatmapRadius(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, heatmapRadius(0.3f))
- )
- ).withDefaultValue(heatmapRadius(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getHeatmapRadius());
- assertNotNull(layer.getHeatmapRadius().getFunction());
- assertEquals(SourceFunction.class, layer.getHeatmapRadius().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapRadius().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getHeatmapRadius().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getHeatmapRadius().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getHeatmapRadius().getFunction()).getDefaultValue().getValue());
- }
- });
- }
@Test
- public void testHeatmapRadiusAsCompositeFunction() {
+ public void testHeatmapRadiusTransition() {
validateTestSetup();
setupLayer();
- Timber.i("heatmap-radius");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- heatmapRadius(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, heatmapRadius(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(heatmapRadius(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getHeatmapRadius());
- assertNotNull(layer.getHeatmapRadius().getFunction());
- assertEquals(CompositeFunction.class, layer.getHeatmapRadius().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getHeatmapRadius().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getHeatmapRadius().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getHeatmapRadius().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getHeatmapRadius().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
+ Timber.i("heatmap-radiusTransitionOptions");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testHeatmapWeightAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("heatmap-weight");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(heatmapWeight(0.3f));
- assertEquals((Float) layer.getHeatmapWeight().getValue(), (Float) 0.3f);
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setHeatmapRadiusTransition(options);
+ assertEquals(layer.getHeatmapRadiusTransition(), options);
});
}
@Test
- public void testHeatmapWeightAsCameraFunction() {
+ public void testHeatmapRadiusAsConstant() {
validateTestSetup();
setupLayer();
- Timber.i("heatmap-weight");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- heatmapWeight(
- zoom(
- exponential(
- stop(2, heatmapWeight(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getHeatmapWeight());
- assertNotNull(layer.getHeatmapWeight().getFunction());
- assertEquals(CameraFunction.class, layer.getHeatmapWeight().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getHeatmapWeight().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getHeatmapWeight().getFunction().getStops()).size());
- }
- });
- }
+ Timber.i("heatmap-radius");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testHeatmapWeightAsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("heatmap-weight");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- heatmapWeight(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getHeatmapWeight());
- assertNotNull(layer.getHeatmapWeight().getFunction());
- assertEquals(SourceFunction.class, layer.getHeatmapWeight().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapWeight().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass());
- }
+ // Set and Get
+ layer.setProperties(heatmapRadius(0.3f));
+ assertEquals((Float) layer.getHeatmapRadius().getValue(), (Float) 0.3f);
});
}
@Test
- public void testHeatmapWeightAsExponentialSourceFunction() {
+ public void testHeatmapRadiusAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("heatmap-weight");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- heatmapWeight(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, heatmapWeight(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getHeatmapWeight());
- assertNotNull(layer.getHeatmapWeight().getFunction());
- assertEquals(SourceFunction.class, layer.getHeatmapWeight().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapWeight().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass());
- }
+ Timber.i("heatmap-radius-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(heatmapRadius(expression));
+ assertEquals(layer.getHeatmapRadius().getExpression(), expression);
});
}
+
@Test
- public void testHeatmapWeightAsCategoricalSourceFunction() {
+ public void testHeatmapWeightAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("heatmap-weight");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- heatmapWeight(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, heatmapWeight(0.3f))
- )
- ).withDefaultValue(heatmapWeight(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getHeatmapWeight());
- assertNotNull(layer.getHeatmapWeight().getFunction());
- assertEquals(SourceFunction.class, layer.getHeatmapWeight().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getHeatmapWeight().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getHeatmapWeight().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getHeatmapWeight().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getHeatmapWeight().getFunction()).getDefaultValue().getValue());
- }
- });
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+ // Set and Get
+ layer.setProperties(heatmapWeight(0.3f));
+ assertEquals((Float) layer.getHeatmapWeight().getValue(), (Float) 0.3f);
+ });
}
@Test
- public void testHeatmapWeightAsCompositeFunction() {
+ public void testHeatmapWeightAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("heatmap-weight");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- heatmapWeight(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, heatmapWeight(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(heatmapWeight(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getHeatmapWeight());
- assertNotNull(layer.getHeatmapWeight().getFunction());
- assertEquals(CompositeFunction.class, layer.getHeatmapWeight().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getHeatmapWeight().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getHeatmapWeight().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getHeatmapWeight().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getHeatmapWeight().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ Timber.i("heatmap-weight-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(heatmapWeight(expression));
+ assertEquals(layer.getHeatmapWeight().getExpression(), expression);
});
}
+
@Test
public void testHeatmapIntensityTransition() {
validateTestSetup();
setupLayer();
Timber.i("heatmap-intensityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setHeatmapIntensityTransition(options);
- assertEquals(layer.getHeatmapIntensityTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setHeatmapIntensityTransition(options);
+ assertEquals(layer.getHeatmapIntensityTransition(), options);
});
}
@@ -512,47 +200,12 @@ public class HeatmapLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("heatmap-intensity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(heatmapIntensity(0.3f));
- assertEquals((Float) layer.getHeatmapIntensity().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testHeatmapIntensityAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("heatmap-intensity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- heatmapIntensity(
- zoom(
- exponential(
- stop(2, heatmapIntensity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getHeatmapIntensity());
- assertNotNull(layer.getHeatmapIntensity().getFunction());
- assertEquals(CameraFunction.class, layer.getHeatmapIntensity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getHeatmapIntensity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getHeatmapIntensity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getHeatmapIntensity().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(heatmapIntensity(0.3f));
+ assertEquals((Float) layer.getHeatmapIntensity().getValue(), (Float) 0.3f);
});
}
@@ -561,16 +214,13 @@ public class HeatmapLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("heatmap-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setHeatmapOpacityTransition(options);
- assertEquals(layer.getHeatmapOpacityTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setHeatmapOpacityTransition(options);
+ assertEquals(layer.getHeatmapOpacityTransition(), options);
});
}
@@ -579,48 +229,12 @@ public class HeatmapLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("heatmap-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(heatmapOpacity(0.3f));
- assertEquals((Float) layer.getHeatmapOpacity().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testHeatmapOpacityAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("heatmap-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- heatmapOpacity(
- zoom(
- exponential(
- stop(2, heatmapOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getHeatmapOpacity());
- assertNotNull(layer.getHeatmapOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getHeatmapOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getHeatmapOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getHeatmapOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getHeatmapOpacity().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(heatmapOpacity(0.3f));
+ assertEquals((Float) layer.getHeatmapOpacity().getValue(), (Float) 0.3f);
});
}
-
-}
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HillshadeLayerTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HillshadeLayerTest.java
index 1cb7b575be..1fdc6d6dab 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HillshadeLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/HillshadeLayerTest.java
@@ -3,31 +3,18 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
import timber.log.Timber;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
-import com.mapbox.mapboxsdk.style.functions.CameraFunction;
-import com.mapbox.mapboxsdk.style.functions.SourceFunction;
-import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.HillshadeLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
import static org.junit.Assert.*;
import static com.mapbox.mapboxsdk.style.layers.Property.*;
@@ -51,17 +38,14 @@ public class HillshadeLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Timber.i("Adding layer");
- layer = new HillshadeLayer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- // Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new HillshadeLayer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ // Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
});
}
@@ -71,18 +55,15 @@ public class HillshadeLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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);
});
}
@@ -91,47 +72,12 @@ public class HillshadeLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("hillshade-illumination-direction");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(hillshadeIlluminationDirection(0.3f));
- assertEquals((Float) layer.getHillshadeIlluminationDirection().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testHillshadeIlluminationDirectionAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("hillshade-illumination-direction");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- hillshadeIlluminationDirection(
- zoom(
- exponential(
- stop(2, hillshadeIlluminationDirection(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getHillshadeIlluminationDirection());
- assertNotNull(layer.getHillshadeIlluminationDirection().getFunction());
- assertEquals(CameraFunction.class, layer.getHillshadeIlluminationDirection().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getHillshadeIlluminationDirection().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getHillshadeIlluminationDirection().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getHillshadeIlluminationDirection().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(hillshadeIlluminationDirection(0.3f));
+ assertEquals((Float) layer.getHillshadeIlluminationDirection().getValue(), (Float) 0.3f);
});
}
@@ -140,46 +86,12 @@ public class HillshadeLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("hillshade-illumination-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(hillshadeIlluminationAnchor(HILLSHADE_ILLUMINATION_ANCHOR_MAP));
- assertEquals((String) layer.getHillshadeIlluminationAnchor().getValue(), (String) HILLSHADE_ILLUMINATION_ANCHOR_MAP);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testHillshadeIlluminationAnchorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("hillshade-illumination-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- hillshadeIlluminationAnchor(
- zoom(
- interval(
- stop(2, hillshadeIlluminationAnchor(HILLSHADE_ILLUMINATION_ANCHOR_MAP))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getHillshadeIlluminationAnchor());
- assertNotNull(layer.getHillshadeIlluminationAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getHillshadeIlluminationAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getHillshadeIlluminationAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getHillshadeIlluminationAnchor().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(hillshadeIlluminationAnchor(HILLSHADE_ILLUMINATION_ANCHOR_MAP));
+ assertEquals((String) layer.getHillshadeIlluminationAnchor().getValue(), (String) HILLSHADE_ILLUMINATION_ANCHOR_MAP);
});
}
@@ -188,16 +100,13 @@ public class HillshadeLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("hillshade-exaggerationTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setHillshadeExaggerationTransition(options);
- assertEquals(layer.getHillshadeExaggerationTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setHillshadeExaggerationTransition(options);
+ assertEquals(layer.getHillshadeExaggerationTransition(), options);
});
}
@@ -206,47 +115,12 @@ public class HillshadeLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("hillshade-exaggeration");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(hillshadeExaggeration(0.3f));
- assertEquals((Float) layer.getHillshadeExaggeration().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testHillshadeExaggerationAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("hillshade-exaggeration");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- hillshadeExaggeration(
- zoom(
- exponential(
- stop(2, hillshadeExaggeration(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getHillshadeExaggeration());
- assertNotNull(layer.getHillshadeExaggeration().getFunction());
- assertEquals(CameraFunction.class, layer.getHillshadeExaggeration().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getHillshadeExaggeration().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getHillshadeExaggeration().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getHillshadeExaggeration().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(hillshadeExaggeration(0.3f));
+ assertEquals((Float) layer.getHillshadeExaggeration().getValue(), (Float) 0.3f);
});
}
@@ -255,16 +129,13 @@ public class HillshadeLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("hillshade-shadow-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setHillshadeShadowColorTransition(options);
- assertEquals(layer.getHillshadeShadowColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setHillshadeShadowColorTransition(options);
+ assertEquals(layer.getHillshadeShadowColorTransition(), options);
});
}
@@ -273,47 +144,12 @@ public class HillshadeLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("hillshade-shadow-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(hillshadeShadowColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getHillshadeShadowColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testHillshadeShadowColorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("hillshade-shadow-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- hillshadeShadowColor(
- zoom(
- exponential(
- stop(2, hillshadeShadowColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getHillshadeShadowColor());
- assertNotNull(layer.getHillshadeShadowColor().getFunction());
- assertEquals(CameraFunction.class, layer.getHillshadeShadowColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getHillshadeShadowColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getHillshadeShadowColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getHillshadeShadowColor().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(hillshadeShadowColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getHillshadeShadowColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -322,15 +158,12 @@ public class HillshadeLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("hillshade-shadow-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(hillshadeShadowColor(Color.RED));
- assertEquals(layer.getHillshadeShadowColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(hillshadeShadowColor(Color.RED));
+ assertEquals(layer.getHillshadeShadowColorAsInt(), Color.RED);
});
}
@@ -339,16 +172,13 @@ public class HillshadeLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("hillshade-highlight-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setHillshadeHighlightColorTransition(options);
- assertEquals(layer.getHillshadeHighlightColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setHillshadeHighlightColorTransition(options);
+ assertEquals(layer.getHillshadeHighlightColorTransition(), options);
});
}
@@ -357,47 +187,12 @@ public class HillshadeLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("hillshade-highlight-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(hillshadeHighlightColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getHillshadeHighlightColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testHillshadeHighlightColorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("hillshade-highlight-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- hillshadeHighlightColor(
- zoom(
- exponential(
- stop(2, hillshadeHighlightColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getHillshadeHighlightColor());
- assertNotNull(layer.getHillshadeHighlightColor().getFunction());
- assertEquals(CameraFunction.class, layer.getHillshadeHighlightColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getHillshadeHighlightColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getHillshadeHighlightColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getHillshadeHighlightColor().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(hillshadeHighlightColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getHillshadeHighlightColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -406,15 +201,12 @@ public class HillshadeLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("hillshade-highlight-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(hillshadeHighlightColor(Color.RED));
- assertEquals(layer.getHillshadeHighlightColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(hillshadeHighlightColor(Color.RED));
+ assertEquals(layer.getHillshadeHighlightColorAsInt(), Color.RED);
});
}
@@ -423,16 +215,13 @@ public class HillshadeLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("hillshade-accent-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setHillshadeAccentColorTransition(options);
- assertEquals(layer.getHillshadeAccentColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setHillshadeAccentColorTransition(options);
+ assertEquals(layer.getHillshadeAccentColorTransition(), options);
});
}
@@ -441,47 +230,12 @@ public class HillshadeLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("hillshade-accent-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(hillshadeAccentColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getHillshadeAccentColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testHillshadeAccentColorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("hillshade-accent-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- hillshadeAccentColor(
- zoom(
- exponential(
- stop(2, hillshadeAccentColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getHillshadeAccentColor());
- assertNotNull(layer.getHillshadeAccentColor().getFunction());
- assertEquals(CameraFunction.class, layer.getHillshadeAccentColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getHillshadeAccentColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getHillshadeAccentColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getHillshadeAccentColor().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(hillshadeAccentColor("rgba(0, 0, 0, 1)"));
+ assertEquals((String) layer.getHillshadeAccentColor().getValue(), (String) "rgba(0, 0, 0, 1)");
});
}
@@ -490,16 +244,12 @@ public class HillshadeLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("hillshade-accent-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(hillshadeAccentColor(Color.RED));
- assertEquals(layer.getHillshadeAccentColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(hillshadeAccentColor(Color.RED));
+ assertEquals(layer.getHillshadeAccentColorAsInt(), Color.RED);
});
}
-
-}
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java
index 88da6e45be..52881e2fe6 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/LightTest.java
@@ -6,15 +6,12 @@ import android.support.test.espresso.ViewAction;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.light.Light;
-import com.mapbox.mapboxsdk.style.functions.Function;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
import com.mapbox.mapboxsdk.style.light.Position;
import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.style.FillExtrusionStyleTestActivity;
@@ -27,7 +24,7 @@ import org.junit.runner.RunWith;
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 com.mapbox.mapboxsdk.style.layers.Filter.eq;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
import static com.mapbox.mapboxsdk.style.layers.Property.ANCHOR_MAP;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionBase;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionColor;
@@ -48,14 +45,11 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- light.setAnchor(ANCHOR_MAP);
- assertEquals("Anchor should match", ANCHOR_MAP, light.getAnchor());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ light.setAnchor(ANCHOR_MAP);
+ assertEquals("Anchor should match", ANCHOR_MAP, light.getAnchor());
});
}
@@ -64,15 +58,12 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("positionTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- light.setPositionTransition(options);
- assertEquals("Transition options should match", options, light.getPositionTransition());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ light.setPositionTransition(options);
+ assertEquals("Transition options should match", options, light.getPositionTransition());
});
}
@@ -81,15 +72,12 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("position");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- Position position = new Position(1, 2, 3);
- light.setPosition(position);
- assertEquals("Position should match", position, light.getPosition());
- }
+ invoke(mapboxMap,(uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ Position position = new Position(1, 2, 3);
+ light.setPosition(position);
+ assertEquals("Position should match", position, light.getPosition());
});
}
@@ -98,15 +86,12 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- light.setColorTransition(options);
- assertEquals("Transition options should match", options, light.getColorTransition());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ light.setColorTransition(options);
+ assertEquals("Transition options should match", options, light.getColorTransition());
});
}
@@ -115,14 +100,11 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- light.setColor("rgba(0, 0, 0, 1)");
- assertEquals("Color should match", "rgba(0, 0, 0, 1)".replaceAll("\\s+", ""), light.getColor());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ light.setColor("rgba(0, 0, 0, 1)");
+ assertEquals("Color should match", "rgba(0, 0, 0, 1)".replaceAll("\\s+", ""), light.getColor());
});
}
@@ -131,15 +113,12 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("intensityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- light.setIntensityTransition(options);
- assertEquals("Transition options should match", options, light.getIntensityTransition());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ light.setIntensityTransition(options);
+ assertEquals("Transition options should match", options, light.getIntensityTransition());
});
}
@@ -148,14 +127,11 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("intensity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- light.setIntensity(0.3f);
- assertEquals("Intensity should match", 0.3f, light.getIntensity());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ light.setIntensity(0.3f);
+ assertEquals("Intensity should match", 0.3f, light.getIntensity());
});
}
@@ -176,12 +152,12 @@ public class LightTest extends BaseActivityTest {
light = mapboxMap.getLight();
FillExtrusionLayer fillExtrusionLayer = new FillExtrusionLayer("3d-buildings", "composite");
fillExtrusionLayer.setSourceLayer("building");
- fillExtrusionLayer.setFilter(eq("extrude", "true"));
+ fillExtrusionLayer.setFilter(eq(Expression.get("extrude"), "true"));
fillExtrusionLayer.setMinZoom(15);
fillExtrusionLayer.setProperties(
fillExtrusionColor(Color.LTGRAY),
- fillExtrusionHeight(Function.property("height", new IdentityStops<Float>())),
- fillExtrusionBase(Function.property("min_height", new IdentityStops<Float>())),
+ fillExtrusionHeight(Expression.get("height")),
+ fillExtrusionBase(Expression.get("min_height")),
fillExtrusionOpacity(0.6f)
);
mapboxMap.addLayer(fillExtrusionLayer);
@@ -193,4 +169,4 @@ public class LightTest extends BaseActivityTest {
protected Class getActivityClass() {
return FillExtrusionStyleTestActivity.class;
}
-}
+} \ No newline at end of file
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 8123d24be8..40cf0f2927 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
@@ -3,31 +3,18 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
import timber.log.Timber;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
-import com.mapbox.mapboxsdk.style.functions.CameraFunction;
-import com.mapbox.mapboxsdk.style.functions.SourceFunction;
-import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.LineLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
import static org.junit.Assert.*;
import static com.mapbox.mapboxsdk.style.layers.Property.*;
@@ -51,17 +38,14 @@ public class LineLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- 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");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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");
}
});
}
@@ -71,18 +55,15 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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);
});
}
@@ -91,67 +72,50 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("SourceLayer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Get initial
- assertEquals(layer.getSourceLayer(), "composite");
-
- // Set
- final String sourceLayer = "test";
- layer.setSourceLayer(sourceLayer);
- assertEquals(layer.getSourceLayer(), sourceLayer);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
});
}
@Test
- public void testLineCapAsConstant() {
+ public void testFilter() {
validateTestSetup();
setupLayer();
- Timber.i("line-cap");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineCap(LINE_CAP_BUTT));
- assertEquals((String) layer.getLineCap().getValue(), (String) LINE_CAP_BUTT);
- }
+ Timber.i("Filter");
+ invoke(mapboxMap, (uiController, mapboxMap1) -> {
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getFilter(), null);
+
+ // Set
+ Expression filter = eq(get("undefined"), literal(1.0));
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
});
}
+
+
@Test
- public void testLineCapAsCameraFunction() {
+ public void testLineCapAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("line-cap");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineCap(
- zoom(
- interval(
- stop(2, lineCap(LINE_CAP_BUTT))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineCap());
- assertNotNull(layer.getLineCap().getFunction());
- assertEquals(CameraFunction.class, layer.getLineCap().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getLineCap().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getLineCap().getFunction().getStops()).size());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineCap(LINE_CAP_BUTT));
+ assertEquals((String) layer.getLineCap().getValue(), (String) LINE_CAP_BUTT);
});
}
@@ -160,152 +124,42 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-join");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineJoin(LINE_JOIN_BEVEL));
- assertEquals((String) layer.getLineJoin().getValue(), (String) LINE_JOIN_BEVEL);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineJoinAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-join");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineJoin(
- zoom(
- interval(
- stop(2, lineJoin(LINE_JOIN_BEVEL))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineJoin());
- assertNotNull(layer.getLineJoin().getFunction());
- assertEquals(CameraFunction.class, layer.getLineJoin().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getLineJoin().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getLineJoin().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(lineJoin(LINE_JOIN_BEVEL));
+ assertEquals((String) layer.getLineJoin().getValue(), (String) LINE_JOIN_BEVEL);
});
}
@Test
- public void testLineJoinAsIdentitySourceFunction() {
+ public void testLineJoinAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("line-join");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineJoin(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getLineJoin());
- assertNotNull(layer.getLineJoin().getFunction());
- assertEquals(SourceFunction.class, layer.getLineJoin().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineJoin().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getLineJoin().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("line-join-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineJoinAsIntervalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-join");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineJoin(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, lineJoin(LINE_JOIN_BEVEL))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineJoin());
- assertNotNull(layer.getLineJoin().getFunction());
- assertEquals(SourceFunction.class, layer.getLineJoin().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineJoin().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getLineJoin().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(lineJoin(expression));
+ assertEquals(layer.getLineJoin().getExpression(), expression);
});
}
+
@Test
public void testLineMiterLimitAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("line-miter-limit");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineMiterLimit(0.3f));
- assertEquals((Float) layer.getLineMiterLimit().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineMiterLimitAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-miter-limit");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineMiterLimit(
- zoom(
- exponential(
- stop(2, lineMiterLimit(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineMiterLimit());
- assertNotNull(layer.getLineMiterLimit().getFunction());
- assertEquals(CameraFunction.class, layer.getLineMiterLimit().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineMiterLimit().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineMiterLimit().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineMiterLimit().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(lineMiterLimit(0.3f));
+ assertEquals((Float) layer.getLineMiterLimit().getValue(), (Float) 0.3f);
});
}
@@ -314,47 +168,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-round-limit");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineRoundLimit(0.3f));
- assertEquals((Float) layer.getLineRoundLimit().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineRoundLimitAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-round-limit");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineRoundLimit(
- zoom(
- exponential(
- stop(2, lineRoundLimit(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineRoundLimit());
- assertNotNull(layer.getLineRoundLimit().getFunction());
- assertEquals(CameraFunction.class, layer.getLineRoundLimit().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineRoundLimit().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineRoundLimit().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineRoundLimit().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(lineRoundLimit(0.3f));
+ assertEquals((Float) layer.getLineRoundLimit().getValue(), (Float) 0.3f);
});
}
@@ -363,216 +182,58 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineOpacityTransition(options);
- assertEquals(layer.getLineOpacityTransition(), options);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineOpacityAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineOpacity(0.3f));
- assertEquals((Float) layer.getLineOpacity().getValue(), (Float) 0.3f);
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineOpacityTransition(options);
+ assertEquals(layer.getLineOpacityTransition(), options);
});
}
@Test
- public void testLineOpacityAsCameraFunction() {
+ public void testLineOpacityAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("line-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOpacity(
- zoom(
- exponential(
- stop(2, lineOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineOpacity());
- assertNotNull(layer.getLineOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getLineOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineOpacity().getFunction().getStops()).size());
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineOpacityAsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getLineOpacity());
- assertNotNull(layer.getLineOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getLineOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOpacity().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
- }
+ // Set and Get
+ layer.setProperties(lineOpacity(0.3f));
+ assertEquals((Float) layer.getLineOpacity().getValue(), (Float) 0.3f);
});
}
@Test
- public void testLineOpacityAsExponentialSourceFunction() {
+ public void testLineOpacityAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("line-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOpacity(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, lineOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineOpacity());
- assertNotNull(layer.getLineOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getLineOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("line-opacity-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineOpacityAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOpacity(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, lineOpacity(0.3f))
- )
- ).withDefaultValue(lineOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineOpacity());
- assertNotNull(layer.getLineOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getLineOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOpacity().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getLineOpacity().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getLineOpacity().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getLineOpacity().getFunction()).getDefaultValue().getValue());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(lineOpacity(expression));
+ assertEquals(layer.getLineOpacity().getExpression(), expression);
});
-
}
- @Test
- public void testLineOpacityAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOpacity(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, lineOpacity(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(lineOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineOpacity());
- assertNotNull(layer.getLineOpacity().getFunction());
- assertEquals(CompositeFunction.class, layer.getLineOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineOpacity().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getLineOpacity().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineOpacity().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testLineColorTransition() {
validateTestSetup();
setupLayer();
Timber.i("line-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineColorTransition(options);
- assertEquals(layer.getLineColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineColorTransition(options);
+ assertEquals(layer.getLineColorTransition(), options);
});
}
@@ -581,157 +242,42 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getLineColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineColorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineColor(
- zoom(
- exponential(
- stop(2, lineColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineColor());
- assertNotNull(layer.getLineColor().getFunction());
- assertEquals(CameraFunction.class, layer.getLineColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineColor().getFunction().getStops()).size());
- }
+ // 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 testLineColorAsIdentitySourceFunction() {
+ public void testLineColorAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("line-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getLineColor());
- assertNotNull(layer.getLineColor().getFunction());
- assertEquals(SourceFunction.class, layer.getLineColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getLineColor().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("line-color-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineColorAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, lineColor(Color.RED))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineColor());
- assertNotNull(layer.getLineColor().getFunction());
- assertEquals(SourceFunction.class, layer.getLineColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineColor().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(lineColor(expression));
+ assertEquals(layer.getLineColor().getExpression(), expression);
});
}
- @Test
- public void testLineColorAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", lineColor(Color.RED))
- )
- ).withDefaultValue(lineColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineColor());
- assertNotNull(layer.getLineColor().getFunction());
- assertEquals(SourceFunction.class, layer.getLineColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getLineColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getLineColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getLineColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getLineColor().getFunction()).getDefaultValue().getColorInt());
- }
- });
-
- }
@Test
public void testLineColorAsIntConstant() {
validateTestSetup();
setupLayer();
Timber.i("line-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineColor(Color.RED));
- assertEquals(layer.getLineColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(lineColor(Color.RED));
+ assertEquals(layer.getLineColorAsInt(), Color.RED);
});
}
@@ -740,16 +286,13 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-translateTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineTranslateTransition(options);
- assertEquals(layer.getLineTranslateTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineTranslateTransition(options);
+ assertEquals(layer.getLineTranslateTransition(), options);
});
}
@@ -758,47 +301,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineTranslate(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getLineTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineTranslateAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineTranslate(
- zoom(
- exponential(
- stop(2, lineTranslate(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineTranslate());
- assertNotNull(layer.getLineTranslate().getFunction());
- assertEquals(CameraFunction.class, layer.getLineTranslate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineTranslate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineTranslate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineTranslate().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(lineTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getLineTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -807,46 +315,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineTranslateAnchor(LINE_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getLineTranslateAnchor().getValue(), (String) LINE_TRANSLATE_ANCHOR_MAP);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineTranslateAnchorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineTranslateAnchor(
- zoom(
- interval(
- stop(2, lineTranslateAnchor(LINE_TRANSLATE_ANCHOR_MAP))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineTranslateAnchor());
- assertNotNull(layer.getLineTranslateAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getLineTranslateAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getLineTranslateAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getLineTranslateAnchor().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(lineTranslateAnchor(LINE_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getLineTranslateAnchor().getValue(), (String) LINE_TRANSLATE_ANCHOR_MAP);
});
}
@@ -855,16 +329,13 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-widthTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineWidthTransition(options);
- assertEquals(layer.getLineWidthTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineWidthTransition(options);
+ assertEquals(layer.getLineWidthTransition(), options);
});
}
@@ -873,198 +344,43 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineWidth(0.3f));
- assertEquals((Float) layer.getLineWidth().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineWidthAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineWidth(
- zoom(
- exponential(
- stop(2, lineWidth(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(lineWidth(0.3f));
+ assertEquals((Float) layer.getLineWidth().getValue(), (Float) 0.3f);
});
}
@Test
- public void testLineWidthAsIdentitySourceFunction() {
+ public void testLineWidthAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("line-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineWidth(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineWidth().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("line-width-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineWidthAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineWidth(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, lineWidth(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(lineWidth(expression));
+ assertEquals(layer.getLineWidth().getExpression(), expression);
});
}
- @Test
- public void testLineWidthAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineWidth(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, lineWidth(0.3f))
- )
- ).withDefaultValue(lineWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineWidth().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getLineWidth().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getLineWidth().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getLineWidth().getFunction()).getDefaultValue().getValue());
- }
- });
-
- }
-
- @Test
- public void testLineWidthAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineWidth(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, lineWidth(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(lineWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineWidth());
- assertNotNull(layer.getLineWidth().getFunction());
- assertEquals(CompositeFunction.class, layer.getLineWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineWidth().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getLineWidth().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineWidth().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testLineGapWidthTransition() {
validateTestSetup();
setupLayer();
Timber.i("line-gap-widthTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineGapWidthTransition(options);
- assertEquals(layer.getLineGapWidthTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineGapWidthTransition(options);
+ assertEquals(layer.getLineGapWidthTransition(), options);
});
}
@@ -1073,380 +389,57 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-gap-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineGapWidth(0.3f));
- assertEquals((Float) layer.getLineGapWidth().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineGapWidthAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-gap-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineGapWidth(
- zoom(
- exponential(
- stop(2, lineGapWidth(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineGapWidth());
- assertNotNull(layer.getLineGapWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getLineGapWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineGapWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineGapWidth().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(lineGapWidth(0.3f));
+ assertEquals((Float) layer.getLineGapWidth().getValue(), (Float) 0.3f);
});
}
@Test
- public void testLineGapWidthAsIdentitySourceFunction() {
+ public void testLineGapWidthAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("line-gap-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineGapWidth(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getLineGapWidth());
- assertNotNull(layer.getLineGapWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getLineGapWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineGapWidth().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("line-gap-width-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineGapWidthAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-gap-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineGapWidth(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, lineGapWidth(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineGapWidth());
- assertNotNull(layer.getLineGapWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getLineGapWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineGapWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(lineGapWidth(expression));
+ assertEquals(layer.getLineGapWidth().getExpression(), expression);
});
}
- @Test
- public void testLineGapWidthAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-gap-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineGapWidth(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, lineGapWidth(0.3f))
- )
- ).withDefaultValue(lineGapWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineGapWidth());
- assertNotNull(layer.getLineGapWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getLineGapWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineGapWidth().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getLineGapWidth().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getLineGapWidth().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getLineGapWidth().getFunction()).getDefaultValue().getValue());
- }
- });
-
- }
-
- @Test
- public void testLineGapWidthAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-gap-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineGapWidth(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, lineGapWidth(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(lineGapWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineGapWidth());
- assertNotNull(layer.getLineGapWidth().getFunction());
- assertEquals(CompositeFunction.class, layer.getLineGapWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineGapWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineGapWidth().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getLineGapWidth().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineGapWidth().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testLineOffsetTransition() {
validateTestSetup();
setupLayer();
Timber.i("line-offsetTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineOffsetTransition(options);
- assertEquals(layer.getLineOffsetTransition(), options);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineOffsetAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineOffset(0.3f));
- assertEquals((Float) layer.getLineOffset().getValue(), (Float) 0.3f);
- }
- });
- }
-
- @Test
- public void testLineOffsetAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOffset(
- zoom(
- exponential(
- stop(2, lineOffset(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
- }
- });
- }
-
- @Test
- public void testLineOffsetAsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOffset(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(SourceFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOffset().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineOffsetTransition(options);
+ assertEquals(layer.getLineOffsetTransition(), options);
});
}
@Test
- public void testLineOffsetAsExponentialSourceFunction() {
+ public void testLineOffsetAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("line-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOffset(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, lineOffset(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(SourceFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOffset().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineOffsetAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOffset(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, lineOffset(0.3f))
- )
- ).withDefaultValue(lineOffset(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(SourceFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineOffset().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getLineOffset().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getLineOffset().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getLineOffset().getFunction()).getDefaultValue().getValue());
- }
- });
-
- }
-
- @Test
- public void testLineOffsetAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineOffset(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, lineOffset(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(lineOffset(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineOffset());
- assertNotNull(layer.getLineOffset().getFunction());
- assertEquals(CompositeFunction.class, layer.getLineOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineOffset().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineOffset().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getLineOffset().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineOffset().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
+ // Set and Get
+ layer.setProperties(lineOffset(0.3f));
+ assertEquals((Float) layer.getLineOffset().getValue(), (Float) 0.3f);
});
}
@@ -1455,216 +448,58 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-blurTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineBlurTransition(options);
- assertEquals(layer.getLineBlurTransition(), options);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineBlurAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineBlur(0.3f));
- assertEquals((Float) layer.getLineBlur().getValue(), (Float) 0.3f);
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineBlurTransition(options);
+ assertEquals(layer.getLineBlurTransition(), options);
});
}
@Test
- public void testLineBlurAsCameraFunction() {
+ public void testLineBlurAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("line-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineBlur(
- zoom(
- exponential(
- stop(2, lineBlur(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineBlur());
- assertNotNull(layer.getLineBlur().getFunction());
- assertEquals(CameraFunction.class, layer.getLineBlur().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getLineBlur().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getLineBlur().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getLineBlur().getFunction().getStops()).size());
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineBlurAsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineBlur(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getLineBlur());
- assertNotNull(layer.getLineBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getLineBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineBlur().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getLineBlur().getFunction().getStops().getClass());
- }
+ // Set and Get
+ layer.setProperties(lineBlur(0.3f));
+ assertEquals((Float) layer.getLineBlur().getValue(), (Float) 0.3f);
});
}
@Test
- public void testLineBlurAsExponentialSourceFunction() {
+ public void testLineBlurAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("line-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineBlur(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, lineBlur(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineBlur());
- assertNotNull(layer.getLineBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getLineBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineBlur().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("line-blur-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineBlurAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineBlur(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, lineBlur(0.3f))
- )
- ).withDefaultValue(lineBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineBlur());
- assertNotNull(layer.getLineBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getLineBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getLineBlur().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getLineBlur().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getLineBlur().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getLineBlur().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getLineBlur().getFunction()).getDefaultValue().getValue());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(lineBlur(expression));
+ assertEquals(layer.getLineBlur().getExpression(), expression);
});
-
}
- @Test
- public void testLineBlurAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineBlur(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, lineBlur(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(lineBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getLineBlur());
- assertNotNull(layer.getLineBlur().getFunction());
- assertEquals(CompositeFunction.class, layer.getLineBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getLineBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getLineBlur().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getLineBlur().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getLineBlur().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testLineDasharrayTransition() {
validateTestSetup();
setupLayer();
Timber.i("line-dasharrayTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLineDasharrayTransition(options);
- assertEquals(layer.getLineDasharrayTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLineDasharrayTransition(options);
+ assertEquals(layer.getLineDasharrayTransition(), options);
});
}
@@ -1673,46 +508,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-dasharray");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(lineDasharray(new Float[] {}));
- assertEquals((Float[]) layer.getLineDasharray().getValue(), (Float[]) new Float[] {});
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLineDasharrayAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-dasharray");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- lineDasharray(
- zoom(
- interval(
- stop(2, lineDasharray(new Float[] {}))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLineDasharray());
- assertNotNull(layer.getLineDasharray().getFunction());
- assertEquals(CameraFunction.class, layer.getLineDasharray().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getLineDasharray().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getLineDasharray().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(lineDasharray(new Float[] {}));
+ assertEquals((Float[]) layer.getLineDasharray().getValue(), (Float[]) new Float[] {});
});
}
@@ -1721,16 +522,13 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-patternTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setLinePatternTransition(options);
- assertEquals(layer.getLinePatternTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setLinePatternTransition(options);
+ assertEquals(layer.getLinePatternTransition(), options);
});
}
@@ -1739,47 +537,12 @@ public class LineLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("line-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(linePattern("pedestrian-polygon"));
- assertEquals((String) layer.getLinePattern().getValue(), (String) "pedestrian-polygon");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testLinePatternAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("line-pattern");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- linePattern(
- zoom(
- interval(
- stop(2, linePattern("pedestrian-polygon"))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getLinePattern());
- assertNotNull(layer.getLinePattern().getFunction());
- assertEquals(CameraFunction.class, layer.getLinePattern().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getLinePattern().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getLinePattern().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(linePattern("pedestrian-polygon"));
+ assertEquals((String) layer.getLinePattern().getValue(), (String) "pedestrian-polygon");
});
}
-
-}
+} \ No newline at end of file
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 df560e2632..0410d09369 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
@@ -3,31 +3,18 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
import timber.log.Timber;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
-import com.mapbox.mapboxsdk.style.functions.CameraFunction;
-import com.mapbox.mapboxsdk.style.functions.SourceFunction;
-import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.RasterLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
import static org.junit.Assert.*;
import static com.mapbox.mapboxsdk.style.layers.Property.*;
@@ -51,17 +38,14 @@ public class RasterLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- 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");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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");
}
});
}
@@ -71,18 +55,15 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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);
});
}
@@ -91,16 +72,13 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setRasterOpacityTransition(options);
- assertEquals(layer.getRasterOpacityTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterOpacityTransition(options);
+ assertEquals(layer.getRasterOpacityTransition(), options);
});
}
@@ -109,47 +87,12 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(rasterOpacity(0.3f));
- assertEquals((Float) layer.getRasterOpacity().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testRasterOpacityAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("raster-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- rasterOpacity(
- zoom(
- exponential(
- stop(2, rasterOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getRasterOpacity());
- assertNotNull(layer.getRasterOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getRasterOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getRasterOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getRasterOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getRasterOpacity().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(rasterOpacity(0.3f));
+ assertEquals((Float) layer.getRasterOpacity().getValue(), (Float) 0.3f);
});
}
@@ -158,16 +101,13 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-hue-rotateTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setRasterHueRotateTransition(options);
- assertEquals(layer.getRasterHueRotateTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterHueRotateTransition(options);
+ assertEquals(layer.getRasterHueRotateTransition(), options);
});
}
@@ -176,47 +116,12 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-hue-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(rasterHueRotate(0.3f));
- assertEquals((Float) layer.getRasterHueRotate().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testRasterHueRotateAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("raster-hue-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- rasterHueRotate(
- zoom(
- exponential(
- stop(2, rasterHueRotate(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getRasterHueRotate());
- assertNotNull(layer.getRasterHueRotate().getFunction());
- assertEquals(CameraFunction.class, layer.getRasterHueRotate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getRasterHueRotate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getRasterHueRotate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getRasterHueRotate().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(rasterHueRotate(0.3f));
+ assertEquals((Float) layer.getRasterHueRotate().getValue(), (Float) 0.3f);
});
}
@@ -225,16 +130,13 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-brightness-minTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setRasterBrightnessMinTransition(options);
- assertEquals(layer.getRasterBrightnessMinTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterBrightnessMinTransition(options);
+ assertEquals(layer.getRasterBrightnessMinTransition(), options);
});
}
@@ -243,47 +145,12 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-brightness-min");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(rasterBrightnessMin(0.3f));
- assertEquals((Float) layer.getRasterBrightnessMin().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testRasterBrightnessMinAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("raster-brightness-min");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- rasterBrightnessMin(
- zoom(
- exponential(
- stop(2, rasterBrightnessMin(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getRasterBrightnessMin());
- assertNotNull(layer.getRasterBrightnessMin().getFunction());
- assertEquals(CameraFunction.class, layer.getRasterBrightnessMin().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getRasterBrightnessMin().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getRasterBrightnessMin().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getRasterBrightnessMin().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(rasterBrightnessMin(0.3f));
+ assertEquals((Float) layer.getRasterBrightnessMin().getValue(), (Float) 0.3f);
});
}
@@ -292,16 +159,13 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-brightness-maxTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setRasterBrightnessMaxTransition(options);
- assertEquals(layer.getRasterBrightnessMaxTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterBrightnessMaxTransition(options);
+ assertEquals(layer.getRasterBrightnessMaxTransition(), options);
});
}
@@ -310,47 +174,12 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-brightness-max");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(rasterBrightnessMax(0.3f));
- assertEquals((Float) layer.getRasterBrightnessMax().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testRasterBrightnessMaxAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("raster-brightness-max");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- rasterBrightnessMax(
- zoom(
- exponential(
- stop(2, rasterBrightnessMax(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getRasterBrightnessMax());
- assertNotNull(layer.getRasterBrightnessMax().getFunction());
- assertEquals(CameraFunction.class, layer.getRasterBrightnessMax().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getRasterBrightnessMax().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getRasterBrightnessMax().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getRasterBrightnessMax().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(rasterBrightnessMax(0.3f));
+ assertEquals((Float) layer.getRasterBrightnessMax().getValue(), (Float) 0.3f);
});
}
@@ -359,16 +188,13 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-saturationTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setRasterSaturationTransition(options);
- assertEquals(layer.getRasterSaturationTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterSaturationTransition(options);
+ assertEquals(layer.getRasterSaturationTransition(), options);
});
}
@@ -377,47 +203,12 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-saturation");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(rasterSaturation(0.3f));
- assertEquals((Float) layer.getRasterSaturation().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testRasterSaturationAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("raster-saturation");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- rasterSaturation(
- zoom(
- exponential(
- stop(2, rasterSaturation(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getRasterSaturation());
- assertNotNull(layer.getRasterSaturation().getFunction());
- assertEquals(CameraFunction.class, layer.getRasterSaturation().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getRasterSaturation().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getRasterSaturation().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getRasterSaturation().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(rasterSaturation(0.3f));
+ assertEquals((Float) layer.getRasterSaturation().getValue(), (Float) 0.3f);
});
}
@@ -426,16 +217,13 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-contrastTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setRasterContrastTransition(options);
- assertEquals(layer.getRasterContrastTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setRasterContrastTransition(options);
+ assertEquals(layer.getRasterContrastTransition(), options);
});
}
@@ -444,47 +232,12 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-contrast");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(rasterContrast(0.3f));
- assertEquals((Float) layer.getRasterContrast().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testRasterContrastAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("raster-contrast");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- rasterContrast(
- zoom(
- exponential(
- stop(2, rasterContrast(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getRasterContrast());
- assertNotNull(layer.getRasterContrast().getFunction());
- assertEquals(CameraFunction.class, layer.getRasterContrast().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getRasterContrast().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getRasterContrast().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getRasterContrast().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(rasterContrast(0.3f));
+ assertEquals((Float) layer.getRasterContrast().getValue(), (Float) 0.3f);
});
}
@@ -493,48 +246,12 @@ public class RasterLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("raster-fade-duration");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(rasterFadeDuration(0.3f));
- assertEquals((Float) layer.getRasterFadeDuration().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testRasterFadeDurationAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("raster-fade-duration");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- rasterFadeDuration(
- zoom(
- exponential(
- stop(2, rasterFadeDuration(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getRasterFadeDuration());
- assertNotNull(layer.getRasterFadeDuration().getFunction());
- assertEquals(CameraFunction.class, layer.getRasterFadeDuration().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getRasterFadeDuration().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getRasterFadeDuration().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getRasterFadeDuration().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(rasterFadeDuration(0.3f));
+ assertEquals((Float) layer.getRasterFadeDuration().getValue(), (Float) 0.3f);
});
}
-
-}
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/StyleLoaderTest.java b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/StyleLoaderTest.java
new file mode 100644
index 0000000000..1a5201193c
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/StyleLoaderTest.java
@@ -0,0 +1,77 @@
+package com.mapbox.mapboxsdk.testapp.style;
+
+
+import android.support.test.espresso.UiController;
+
+import com.mapbox.mapboxsdk.maps.MapView;
+import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
+import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
+import com.mapbox.mapboxsdk.testapp.activity.espresso.EspressoTestActivity;
+import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
+
+import org.junit.Test;
+
+import java.io.IOException;
+
+import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Tests around style loading
+ */
+public class StyleLoaderTest extends BaseActivityTest {
+
+
+ @Override
+ protected Class getActivityClass() {
+ return EspressoTestActivity.class;
+ }
+
+ @Test
+ public void testSetGetStyleJsonString() throws Exception {
+ validateTestSetup();
+ invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
+ @Override
+ public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
+ try {
+ String expected = ResourceUtils.readRawResource(rule.getActivity(), R.raw.local_style);
+ mapboxMap.setStyleJson(expected);
+ String actual = mapboxMap.getStyleJson();
+ assertEquals("Style json should match", expected, actual);
+ } catch (IOException exception) {
+ exception.printStackTrace();
+ }
+ }
+ });
+ }
+
+ @Test
+ public void testDefaultStyleLoadWithActivityLifecycleChange() throws Exception {
+ validateTestSetup();
+ invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
+ @Override
+ public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
+ try {
+ String expected = ResourceUtils.readRawResource(rule.getActivity(), R.raw.local_style);
+ mapboxMap.setStyleJson(expected);
+
+ // fake activity stop/start
+ MapView mapView = (MapView) rule.getActivity().findViewById(R.id.mapView);
+ mapView.onPause();
+ mapView.onStop();
+
+ mapView.onStart();
+ mapView.onResume();
+
+ String actual = mapboxMap.getStyleJson();
+ assertEquals("Style URL should be empty", "", mapboxMap.getStyleUrl());
+ assertEquals("Style json should match", expected, actual);
+ } catch (IOException exception) {
+ exception.printStackTrace();
+ }
+ }
+ });
+ }
+} \ No newline at end of file
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 781307862d..62f73b1507 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
@@ -3,31 +3,18 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
import timber.log.Timber;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
-import com.mapbox.mapboxsdk.style.functions.CameraFunction;
-import com.mapbox.mapboxsdk.style.functions.SourceFunction;
-import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
import static org.junit.Assert.*;
import static com.mapbox.mapboxsdk.style.layers.Property.*;
@@ -51,17 +38,14 @@ public class SymbolLayerTest extends BaseActivityTest {
private void setupLayer() {
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- 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");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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");
}
});
}
@@ -71,18 +55,15 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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);
});
}
@@ -91,67 +72,50 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("SourceLayer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Get initial
- assertEquals(layer.getSourceLayer(), "composite");
-
- // Set
- final String sourceLayer = "test";
- layer.setSourceLayer(sourceLayer);
- assertEquals(layer.getSourceLayer(), sourceLayer);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
+
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
});
}
@Test
- public void testSymbolPlacementAsConstant() {
+ public void testFilter() {
validateTestSetup();
setupLayer();
- Timber.i("symbol-placement");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(symbolPlacement(SYMBOL_PLACEMENT_POINT));
- assertEquals((String) layer.getSymbolPlacement().getValue(), (String) SYMBOL_PLACEMENT_POINT);
- }
+ Timber.i("Filter");
+ invoke(mapboxMap, (uiController, mapboxMap1) -> {
+ assertNotNull(layer);
+
+ // Get initial
+ assertEquals(layer.getFilter(), null);
+
+ // Set
+ Expression filter = eq(get("undefined"), literal(1.0));
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
});
}
+
+
@Test
- public void testSymbolPlacementAsCameraFunction() {
+ public void testSymbolPlacementAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("symbol-placement");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- symbolPlacement(
- zoom(
- interval(
- stop(2, symbolPlacement(SYMBOL_PLACEMENT_POINT))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getSymbolPlacement());
- assertNotNull(layer.getSymbolPlacement().getFunction());
- assertEquals(CameraFunction.class, layer.getSymbolPlacement().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getSymbolPlacement().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getSymbolPlacement().getFunction().getStops()).size());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(symbolPlacement(SYMBOL_PLACEMENT_POINT));
+ assertEquals((String) layer.getSymbolPlacement().getValue(), (String) SYMBOL_PLACEMENT_POINT);
});
}
@@ -160,47 +124,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("symbol-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(symbolSpacing(0.3f));
- assertEquals((Float) layer.getSymbolSpacing().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testSymbolSpacingAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("symbol-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- symbolSpacing(
- zoom(
- exponential(
- stop(2, symbolSpacing(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getSymbolSpacing());
- assertNotNull(layer.getSymbolSpacing().getFunction());
- assertEquals(CameraFunction.class, layer.getSymbolSpacing().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getSymbolSpacing().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getSymbolSpacing().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getSymbolSpacing().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(symbolSpacing(0.3f));
+ assertEquals((Float) layer.getSymbolSpacing().getValue(), (Float) 0.3f);
});
}
@@ -209,46 +138,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("symbol-avoid-edges");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(symbolAvoidEdges(true));
- assertEquals((Boolean) layer.getSymbolAvoidEdges().getValue(), (Boolean) true);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testSymbolAvoidEdgesAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("symbol-avoid-edges");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- symbolAvoidEdges(
- zoom(
- interval(
- stop(2, symbolAvoidEdges(true))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getSymbolAvoidEdges());
- assertNotNull(layer.getSymbolAvoidEdges().getFunction());
- assertEquals(CameraFunction.class, layer.getSymbolAvoidEdges().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getSymbolAvoidEdges().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getSymbolAvoidEdges().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(symbolAvoidEdges(true));
+ assertEquals((Boolean) layer.getSymbolAvoidEdges().getValue(), (Boolean) true);
});
}
@@ -257,46 +152,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-allow-overlap");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconAllowOverlap(true));
- assertEquals((Boolean) layer.getIconAllowOverlap().getValue(), (Boolean) true);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconAllowOverlapAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-allow-overlap");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconAllowOverlap(
- zoom(
- interval(
- stop(2, iconAllowOverlap(true))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconAllowOverlap());
- assertNotNull(layer.getIconAllowOverlap().getFunction());
- assertEquals(CameraFunction.class, layer.getIconAllowOverlap().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconAllowOverlap().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconAllowOverlap().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconAllowOverlap(true));
+ assertEquals((Boolean) layer.getIconAllowOverlap().getValue(), (Boolean) true);
});
}
@@ -305,46 +166,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-ignore-placement");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconIgnorePlacement(true));
- assertEquals((Boolean) layer.getIconIgnorePlacement().getValue(), (Boolean) true);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconIgnorePlacementAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-ignore-placement");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconIgnorePlacement(
- zoom(
- interval(
- stop(2, iconIgnorePlacement(true))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconIgnorePlacement());
- assertNotNull(layer.getIconIgnorePlacement().getFunction());
- assertEquals(CameraFunction.class, layer.getIconIgnorePlacement().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconIgnorePlacement().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconIgnorePlacement().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconIgnorePlacement(true));
+ assertEquals((Boolean) layer.getIconIgnorePlacement().getValue(), (Boolean) true);
});
}
@@ -353,46 +180,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-optional");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconOptional(true));
- assertEquals((Boolean) layer.getIconOptional().getValue(), (Boolean) true);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconOptionalAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-optional");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOptional(
- zoom(
- interval(
- stop(2, iconOptional(true))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconOptional());
- assertNotNull(layer.getIconOptional().getFunction());
- assertEquals(CameraFunction.class, layer.getIconOptional().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconOptional().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconOptional().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconOptional(true));
+ assertEquals((Boolean) layer.getIconOptional().getValue(), (Boolean) true);
});
}
@@ -401,46 +194,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-rotation-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconRotationAlignment(ICON_ROTATION_ALIGNMENT_MAP));
- assertEquals((String) layer.getIconRotationAlignment().getValue(), (String) ICON_ROTATION_ALIGNMENT_MAP);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconRotationAlignmentAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-rotation-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconRotationAlignment(
- zoom(
- interval(
- stop(2, iconRotationAlignment(ICON_ROTATION_ALIGNMENT_MAP))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconRotationAlignment());
- assertNotNull(layer.getIconRotationAlignment().getFunction());
- assertEquals(CameraFunction.class, layer.getIconRotationAlignment().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconRotationAlignment().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconRotationAlignment().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconRotationAlignment(ICON_ROTATION_ALIGNMENT_MAP));
+ assertEquals((String) layer.getIconRotationAlignment().getValue(), (String) ICON_ROTATION_ALIGNMENT_MAP);
});
}
@@ -449,228 +208,42 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconSize(0.3f));
- assertEquals((Float) layer.getIconSize().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconSizeAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconSize(
- zoom(
- exponential(
- stop(2, iconSize(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconSize());
- assertNotNull(layer.getIconSize().getFunction());
- assertEquals(CameraFunction.class, layer.getIconSize().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconSize().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconSize().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconSize().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconSize(0.3f));
+ assertEquals((Float) layer.getIconSize().getValue(), (Float) 0.3f);
});
}
@Test
- public void testIconSizeAsIdentitySourceFunction() {
+ public void testIconSizeAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("icon-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconSize(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconSize());
- assertNotNull(layer.getIconSize().getFunction());
- assertEquals(SourceFunction.class, layer.getIconSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconSize().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconSize().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("icon-size-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconSizeAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconSize(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, iconSize(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconSize());
- assertNotNull(layer.getIconSize().getFunction());
- assertEquals(SourceFunction.class, layer.getIconSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconSize().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconSize().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(iconSize(expression));
+ assertEquals(layer.getIconSize().getExpression(), expression);
});
}
- @Test
- public void testIconSizeAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconSize(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, iconSize(0.3f))
- )
- ).withDefaultValue(iconSize(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconSize());
- assertNotNull(layer.getIconSize().getFunction());
- assertEquals(SourceFunction.class, layer.getIconSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconSize().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getIconSize().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getIconSize().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getIconSize().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getIconSize().getFunction()).getDefaultValue().getValue());
- }
- });
-
- }
-
- @Test
- public void testIconSizeAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconSize(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, iconSize(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(iconSize(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconSize());
- assertNotNull(layer.getIconSize().getFunction());
- assertEquals(CompositeFunction.class, layer.getIconSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconSize().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconSize().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getIconSize().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconSize().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testIconTextFitAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("icon-text-fit");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconTextFit(ICON_TEXT_FIT_NONE));
- assertEquals((String) layer.getIconTextFit().getValue(), (String) ICON_TEXT_FIT_NONE);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconTextFitAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-text-fit");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconTextFit(
- zoom(
- interval(
- stop(2, iconTextFit(ICON_TEXT_FIT_NONE))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconTextFit());
- assertNotNull(layer.getIconTextFit().getFunction());
- assertEquals(CameraFunction.class, layer.getIconTextFit().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconTextFit().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconTextFit().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconTextFit(ICON_TEXT_FIT_NONE));
+ assertEquals((String) layer.getIconTextFit().getValue(), (String) ICON_TEXT_FIT_NONE);
});
}
@@ -679,47 +252,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-text-fit-padding");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- 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});
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconTextFitPaddingAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-text-fit-padding");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconTextFitPadding(
- zoom(
- exponential(
- stop(2, iconTextFitPadding(new Float[] {0f, 0f, 0f, 0f}))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconTextFitPadding());
- assertNotNull(layer.getIconTextFitPadding().getFunction());
- assertEquals(CameraFunction.class, layer.getIconTextFitPadding().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconTextFitPadding().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconTextFitPadding().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconTextFitPadding().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconTextFitPadding(new Float[] {0f, 0f, 0f, 0f}));
+ assertEquals((Float[]) layer.getIconTextFitPadding().getValue(), (Float[]) new Float[] {0f, 0f, 0f, 0f});
});
}
@@ -728,334 +266,72 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-image");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconImage("undefined"));
- assertEquals((String) layer.getIconImage().getValue(), (String) "undefined");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconImageAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-image");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconImage(
- zoom(
- interval(
- stop(2, iconImage("undefined"))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconImage());
- assertNotNull(layer.getIconImage().getFunction());
- assertEquals(CameraFunction.class, layer.getIconImage().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconImage().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconImage().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconImage("undefined"));
+ assertEquals((String) layer.getIconImage().getValue(), (String) "undefined");
});
}
@Test
- public void testIconImageAsIdentitySourceFunction() {
+ public void testIconImageAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("icon-image");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconImage(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconImage());
- assertNotNull(layer.getIconImage().getFunction());
- assertEquals(SourceFunction.class, layer.getIconImage().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconImage().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconImage().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("icon-image-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconImageAsIntervalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-image");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconImage(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, iconImage("undefined"))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconImage());
- assertNotNull(layer.getIconImage().getFunction());
- assertEquals(SourceFunction.class, layer.getIconImage().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconImage().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getIconImage().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(iconImage(expression));
+ assertEquals(layer.getIconImage().getExpression(), expression);
});
}
+
@Test
public void testIconRotateAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("icon-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconRotate(0.3f));
- assertEquals((Float) layer.getIconRotate().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconRotateAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconRotate(
- zoom(
- exponential(
- stop(2, iconRotate(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconRotate());
- assertNotNull(layer.getIconRotate().getFunction());
- assertEquals(CameraFunction.class, layer.getIconRotate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconRotate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconRotate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconRotate().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconRotate(0.3f));
+ assertEquals((Float) layer.getIconRotate().getValue(), (Float) 0.3f);
});
}
@Test
- public void testIconRotateAsIdentitySourceFunction() {
+ public void testIconRotateAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("icon-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconRotate(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconRotate());
- assertNotNull(layer.getIconRotate().getFunction());
- assertEquals(SourceFunction.class, layer.getIconRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconRotate().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconRotate().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("icon-rotate-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconRotateAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconRotate(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, iconRotate(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconRotate());
- assertNotNull(layer.getIconRotate().getFunction());
- assertEquals(SourceFunction.class, layer.getIconRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconRotate().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconRotate().getFunction().getStops().getClass());
- }
- });
- }
-
- @Test
- public void testIconRotateAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconRotate(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, iconRotate(0.3f))
- )
- ).withDefaultValue(iconRotate(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconRotate());
- assertNotNull(layer.getIconRotate().getFunction());
- assertEquals(SourceFunction.class, layer.getIconRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconRotate().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getIconRotate().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getIconRotate().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getIconRotate().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getIconRotate().getFunction()).getDefaultValue().getValue());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(iconRotate(expression));
+ assertEquals(layer.getIconRotate().getExpression(), expression);
});
-
}
- @Test
- public void testIconRotateAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconRotate(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, iconRotate(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(iconRotate(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconRotate());
- assertNotNull(layer.getIconRotate().getFunction());
- assertEquals(CompositeFunction.class, layer.getIconRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconRotate().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconRotate().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getIconRotate().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconRotate().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testIconPaddingAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("icon-padding");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconPadding(0.3f));
- assertEquals((Float) layer.getIconPadding().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconPaddingAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-padding");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconPadding(
- zoom(
- exponential(
- stop(2, iconPadding(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconPadding());
- assertNotNull(layer.getIconPadding().getFunction());
- assertEquals(CameraFunction.class, layer.getIconPadding().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconPadding().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconPadding().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconPadding().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconPadding(0.3f));
+ assertEquals((Float) layer.getIconPadding().getValue(), (Float) 0.3f);
});
}
@@ -1064,46 +340,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-keep-upright");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconKeepUpright(true));
- assertEquals((Boolean) layer.getIconKeepUpright().getValue(), (Boolean) true);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconKeepUprightAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-keep-upright");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconKeepUpright(
- zoom(
- interval(
- stop(2, iconKeepUpright(true))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconKeepUpright());
- assertNotNull(layer.getIconKeepUpright().getFunction());
- assertEquals(CameraFunction.class, layer.getIconKeepUpright().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconKeepUpright().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconKeepUpright().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconKeepUpright(true));
+ assertEquals((Boolean) layer.getIconKeepUpright().getValue(), (Boolean) true);
});
}
@@ -1112,104 +354,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconOffset(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getIconOffset().getValue(), (Float[]) new Float[] {0f, 0f});
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconOffsetAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOffset(
- zoom(
- exponential(
- stop(2, iconOffset(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconOffset());
- assertNotNull(layer.getIconOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getIconOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconOffset().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconOffset().getFunction().getStops()).size());
- }
- });
- }
-
- @Test
- public void testIconOffsetAsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOffset(property("FeaturePropertyA", Stops.<Float[]>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconOffset());
- assertNotNull(layer.getIconOffset().getFunction());
- assertEquals(SourceFunction.class, layer.getIconOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOffset().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconOffset().getFunction().getStops().getClass());
- }
- });
- }
-
- @Test
- public void testIconOffsetAsIntervalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOffset(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, iconOffset(new Float[] {0f, 0f}))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconOffset());
- assertNotNull(layer.getIconOffset().getFunction());
- assertEquals(SourceFunction.class, layer.getIconOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOffset().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getIconOffset().getFunction().getStops().getClass());
- }
+ // Set and Get
+ layer.setProperties(iconOffset(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getIconOffset().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -1218,151 +368,42 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconAnchor(ICON_ANCHOR_CENTER));
- assertEquals((String) layer.getIconAnchor().getValue(), (String) ICON_ANCHOR_CENTER);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconAnchorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconAnchor(
- zoom(
- interval(
- stop(2, iconAnchor(ICON_ANCHOR_CENTER))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconAnchor());
- assertNotNull(layer.getIconAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getIconAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconAnchor().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconAnchor(ICON_ANCHOR_CENTER));
+ assertEquals((String) layer.getIconAnchor().getValue(), (String) ICON_ANCHOR_CENTER);
});
}
@Test
- public void testIconAnchorAsIdentitySourceFunction() {
+ public void testIconAnchorAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("icon-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconAnchor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconAnchor());
- assertNotNull(layer.getIconAnchor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconAnchor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconAnchor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconAnchor().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("icon-anchor-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconAnchorAsIntervalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconAnchor(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, iconAnchor(ICON_ANCHOR_CENTER))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconAnchor());
- assertNotNull(layer.getIconAnchor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconAnchor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconAnchor().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getIconAnchor().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(iconAnchor(expression));
+ assertEquals(layer.getIconAnchor().getExpression(), expression);
});
}
+
@Test
public void testIconPitchAlignmentAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("icon-pitch-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconPitchAlignment(ICON_PITCH_ALIGNMENT_MAP));
- assertEquals((String) layer.getIconPitchAlignment().getValue(), (String) ICON_PITCH_ALIGNMENT_MAP);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconPitchAlignmentAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-pitch-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconPitchAlignment(
- zoom(
- interval(
- stop(2, iconPitchAlignment(ICON_PITCH_ALIGNMENT_MAP))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconPitchAlignment());
- assertNotNull(layer.getIconPitchAlignment().getFunction());
- assertEquals(CameraFunction.class, layer.getIconPitchAlignment().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconPitchAlignment().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconPitchAlignment().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconPitchAlignment(ICON_PITCH_ALIGNMENT_MAP));
+ assertEquals((String) layer.getIconPitchAlignment().getValue(), (String) ICON_PITCH_ALIGNMENT_MAP);
});
}
@@ -1371,46 +412,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-pitch-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textPitchAlignment(TEXT_PITCH_ALIGNMENT_MAP));
- assertEquals((String) layer.getTextPitchAlignment().getValue(), (String) TEXT_PITCH_ALIGNMENT_MAP);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextPitchAlignmentAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-pitch-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textPitchAlignment(
- zoom(
- interval(
- stop(2, textPitchAlignment(TEXT_PITCH_ALIGNMENT_MAP))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextPitchAlignment());
- assertNotNull(layer.getTextPitchAlignment().getFunction());
- assertEquals(CameraFunction.class, layer.getTextPitchAlignment().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextPitchAlignment().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextPitchAlignment().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textPitchAlignment(TEXT_PITCH_ALIGNMENT_MAP));
+ assertEquals((String) layer.getTextPitchAlignment().getValue(), (String) TEXT_PITCH_ALIGNMENT_MAP);
});
}
@@ -1419,46 +426,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-rotation-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textRotationAlignment(TEXT_ROTATION_ALIGNMENT_MAP));
- assertEquals((String) layer.getTextRotationAlignment().getValue(), (String) TEXT_ROTATION_ALIGNMENT_MAP);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextRotationAlignmentAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-rotation-alignment");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textRotationAlignment(
- zoom(
- interval(
- stop(2, textRotationAlignment(TEXT_ROTATION_ALIGNMENT_MAP))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextRotationAlignment());
- assertNotNull(layer.getTextRotationAlignment().getFunction());
- assertEquals(CameraFunction.class, layer.getTextRotationAlignment().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextRotationAlignment().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextRotationAlignment().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textRotationAlignment(TEXT_ROTATION_ALIGNMENT_MAP));
+ assertEquals((String) layer.getTextRotationAlignment().getValue(), (String) TEXT_ROTATION_ALIGNMENT_MAP);
});
}
@@ -1467,208 +440,42 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-field");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textField(""));
- assertEquals((String) layer.getTextField().getValue(), (String) "");
- }
- });
- }
-
- @Test
- public void testTextFieldAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-field");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textField(
- zoom(
- interval(
- stop(2, textField(""))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextField());
- assertNotNull(layer.getTextField().getFunction());
- assertEquals(CameraFunction.class, layer.getTextField().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextField().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextField().getFunction().getStops()).size());
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextFieldAsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-field");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textField(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextField());
- assertNotNull(layer.getTextField().getFunction());
- assertEquals(SourceFunction.class, layer.getTextField().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextField().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextField().getFunction().getStops().getClass());
- }
+ // Set and Get
+ layer.setProperties(textField(""));
+ assertEquals((String) layer.getTextField().getValue(), (String) "");
});
}
@Test
- public void testTextFieldAsIntervalSourceFunction() {
+ public void testTextFieldAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("text-field");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textField(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, textField(""))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextField());
- assertNotNull(layer.getTextField().getFunction());
- assertEquals(SourceFunction.class, layer.getTextField().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextField().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getTextField().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("text-field-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextFontAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-font");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- 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"});
- }
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(textField(expression));
+ assertEquals(layer.getTextField().getExpression(), expression);
});
}
- @Test
- public void testTextFontAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-font");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textFont(
- zoom(
- interval(
- stop(2, textFont(new String[]{"Open Sans Regular", "Arial Unicode MS Regular"}))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextFont());
- assertNotNull(layer.getTextFont().getFunction());
- assertEquals(CameraFunction.class, layer.getTextFont().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextFont().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextFont().getFunction().getStops()).size());
- }
- });
- }
@Test
- public void testTextFontAsIdentitySourceFunction() {
+ public void testTextFontAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("text-font");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textFont(property("FeaturePropertyA", Stops.<String[]>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextFont());
- assertNotNull(layer.getTextFont().getFunction());
- assertEquals(SourceFunction.class, layer.getTextFont().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextFont().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextFont().getFunction().getStops().getClass());
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextFontAsIntervalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-font");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textFont(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, textFont(new String[]{"Open Sans Regular", "Arial Unicode MS Regular"}))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextFont());
- assertNotNull(layer.getTextFont().getFunction());
- assertEquals(SourceFunction.class, layer.getTextFont().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextFont().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getTextFont().getFunction().getStops().getClass());
- }
+ // 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"});
});
}
@@ -1677,411 +484,72 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textSize(0.3f));
- assertEquals((Float) layer.getTextSize().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextSizeAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textSize(
- zoom(
- exponential(
- stop(2, textSize(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextSize());
- assertNotNull(layer.getTextSize().getFunction());
- assertEquals(CameraFunction.class, layer.getTextSize().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextSize().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextSize().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextSize().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textSize(0.3f));
+ assertEquals((Float) layer.getTextSize().getValue(), (Float) 0.3f);
});
}
@Test
- public void testTextSizeAsIdentitySourceFunction() {
+ public void testTextSizeAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("text-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textSize(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextSize());
- assertNotNull(layer.getTextSize().getFunction());
- assertEquals(SourceFunction.class, layer.getTextSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextSize().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextSize().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("text-size-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextSizeAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textSize(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, textSize(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextSize());
- assertNotNull(layer.getTextSize().getFunction());
- assertEquals(SourceFunction.class, layer.getTextSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextSize().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextSize().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(textSize(expression));
+ assertEquals(layer.getTextSize().getExpression(), expression);
});
}
- @Test
- public void testTextSizeAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textSize(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, textSize(0.3f))
- )
- ).withDefaultValue(textSize(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextSize());
- assertNotNull(layer.getTextSize().getFunction());
- assertEquals(SourceFunction.class, layer.getTextSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextSize().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextSize().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextSize().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextSize().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getTextSize().getFunction()).getDefaultValue().getValue());
- }
- });
-
- }
-
- @Test
- public void testTextSizeAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-size");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textSize(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, textSize(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(textSize(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextSize());
- assertNotNull(layer.getTextSize().getFunction());
- assertEquals(CompositeFunction.class, layer.getTextSize().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextSize().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextSize().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getTextSize().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextSize().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testTextMaxWidthAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("text-max-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textMaxWidth(0.3f));
- assertEquals((Float) layer.getTextMaxWidth().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextMaxWidthAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-max-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textMaxWidth(
- zoom(
- exponential(
- stop(2, textMaxWidth(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextMaxWidth());
- assertNotNull(layer.getTextMaxWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getTextMaxWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextMaxWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextMaxWidth().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textMaxWidth(0.3f));
+ assertEquals((Float) layer.getTextMaxWidth().getValue(), (Float) 0.3f);
});
}
@Test
- public void testTextMaxWidthAsIdentitySourceFunction() {
+ public void testTextMaxWidthAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("text-max-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textMaxWidth(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextMaxWidth());
- assertNotNull(layer.getTextMaxWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getTextMaxWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextMaxWidth().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("text-max-width-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextMaxWidthAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-max-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textMaxWidth(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, textMaxWidth(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextMaxWidth());
- assertNotNull(layer.getTextMaxWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getTextMaxWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextMaxWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(textMaxWidth(expression));
+ assertEquals(layer.getTextMaxWidth().getExpression(), expression);
});
}
- @Test
- public void testTextMaxWidthAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-max-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textMaxWidth(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, textMaxWidth(0.3f))
- )
- ).withDefaultValue(textMaxWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextMaxWidth());
- assertNotNull(layer.getTextMaxWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getTextMaxWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextMaxWidth().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextMaxWidth().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextMaxWidth().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getTextMaxWidth().getFunction()).getDefaultValue().getValue());
- }
- });
-
- }
-
- @Test
- public void testTextMaxWidthAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-max-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textMaxWidth(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, textMaxWidth(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(textMaxWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextMaxWidth());
- assertNotNull(layer.getTextMaxWidth().getFunction());
- assertEquals(CompositeFunction.class, layer.getTextMaxWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextMaxWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextMaxWidth().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getTextMaxWidth().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextMaxWidth().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testTextLineHeightAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("text-line-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textLineHeight(0.3f));
- assertEquals((Float) layer.getTextLineHeight().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextLineHeightAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-line-height");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textLineHeight(
- zoom(
- exponential(
- stop(2, textLineHeight(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextLineHeight());
- assertNotNull(layer.getTextLineHeight().getFunction());
- assertEquals(CameraFunction.class, layer.getTextLineHeight().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextLineHeight().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextLineHeight().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextLineHeight().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textLineHeight(0.3f));
+ assertEquals((Float) layer.getTextLineHeight().getValue(), (Float) 0.3f);
});
}
@@ -2090,439 +558,102 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-letter-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textLetterSpacing(0.3f));
- assertEquals((Float) layer.getTextLetterSpacing().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextLetterSpacingAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-letter-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textLetterSpacing(
- zoom(
- exponential(
- stop(2, textLetterSpacing(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextLetterSpacing());
- assertNotNull(layer.getTextLetterSpacing().getFunction());
- assertEquals(CameraFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextLetterSpacing().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextLetterSpacing().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textLetterSpacing(0.3f));
+ assertEquals((Float) layer.getTextLetterSpacing().getValue(), (Float) 0.3f);
});
}
@Test
- public void testTextLetterSpacingAsIdentitySourceFunction() {
+ public void testTextLetterSpacingAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("text-letter-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textLetterSpacing(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextLetterSpacing());
- assertNotNull(layer.getTextLetterSpacing().getFunction());
- assertEquals(SourceFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextLetterSpacing().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("text-letter-spacing-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextLetterSpacingAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-letter-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textLetterSpacing(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, textLetterSpacing(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextLetterSpacing());
- assertNotNull(layer.getTextLetterSpacing().getFunction());
- assertEquals(SourceFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextLetterSpacing().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
- }
- });
- }
-
- @Test
- public void testTextLetterSpacingAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-letter-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textLetterSpacing(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, textLetterSpacing(0.3f))
- )
- ).withDefaultValue(textLetterSpacing(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextLetterSpacing());
- assertNotNull(layer.getTextLetterSpacing().getFunction());
- assertEquals(SourceFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextLetterSpacing().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextLetterSpacing().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextLetterSpacing().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getTextLetterSpacing().getFunction()).getDefaultValue().getValue());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(textLetterSpacing(expression));
+ assertEquals(layer.getTextLetterSpacing().getExpression(), expression);
});
-
}
- @Test
- public void testTextLetterSpacingAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-letter-spacing");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textLetterSpacing(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, textLetterSpacing(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(textLetterSpacing(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextLetterSpacing());
- assertNotNull(layer.getTextLetterSpacing().getFunction());
- assertEquals(CompositeFunction.class, layer.getTextLetterSpacing().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextLetterSpacing().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextLetterSpacing().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getTextLetterSpacing().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextLetterSpacing().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testTextJustifyAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("text-justify");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textJustify(TEXT_JUSTIFY_LEFT));
- assertEquals((String) layer.getTextJustify().getValue(), (String) TEXT_JUSTIFY_LEFT);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextJustifyAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-justify");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textJustify(
- zoom(
- interval(
- stop(2, textJustify(TEXT_JUSTIFY_LEFT))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextJustify());
- assertNotNull(layer.getTextJustify().getFunction());
- assertEquals(CameraFunction.class, layer.getTextJustify().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextJustify().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextJustify().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textJustify(TEXT_JUSTIFY_LEFT));
+ assertEquals((String) layer.getTextJustify().getValue(), (String) TEXT_JUSTIFY_LEFT);
});
}
@Test
- public void testTextJustifyAsIdentitySourceFunction() {
+ public void testTextJustifyAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("text-justify");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textJustify(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextJustify());
- assertNotNull(layer.getTextJustify().getFunction());
- assertEquals(SourceFunction.class, layer.getTextJustify().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextJustify().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextJustify().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("text-justify-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextJustifyAsIntervalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-justify");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textJustify(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, textJustify(TEXT_JUSTIFY_LEFT))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextJustify());
- assertNotNull(layer.getTextJustify().getFunction());
- assertEquals(SourceFunction.class, layer.getTextJustify().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextJustify().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getTextJustify().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(textJustify(expression));
+ assertEquals(layer.getTextJustify().getExpression(), expression);
});
}
+
@Test
public void testTextAnchorAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("text-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textAnchor(TEXT_ANCHOR_CENTER));
- assertEquals((String) layer.getTextAnchor().getValue(), (String) TEXT_ANCHOR_CENTER);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextAnchorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textAnchor(
- zoom(
- interval(
- stop(2, textAnchor(TEXT_ANCHOR_CENTER))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextAnchor());
- assertNotNull(layer.getTextAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getTextAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextAnchor().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textAnchor(TEXT_ANCHOR_CENTER));
+ assertEquals((String) layer.getTextAnchor().getValue(), (String) TEXT_ANCHOR_CENTER);
});
}
@Test
- public void testTextAnchorAsIdentitySourceFunction() {
+ public void testTextAnchorAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("text-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textAnchor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextAnchor());
- assertNotNull(layer.getTextAnchor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextAnchor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextAnchor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextAnchor().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("text-anchor-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextAnchorAsIntervalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textAnchor(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, textAnchor(TEXT_ANCHOR_CENTER))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextAnchor());
- assertNotNull(layer.getTextAnchor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextAnchor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextAnchor().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getTextAnchor().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(textAnchor(expression));
+ assertEquals(layer.getTextAnchor().getExpression(), expression);
});
}
+
@Test
public void testTextMaxAngleAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("text-max-angle");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textMaxAngle(0.3f));
- assertEquals((Float) layer.getTextMaxAngle().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextMaxAngleAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-max-angle");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textMaxAngle(
- zoom(
- exponential(
- stop(2, textMaxAngle(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextMaxAngle());
- assertNotNull(layer.getTextMaxAngle().getFunction());
- assertEquals(CameraFunction.class, layer.getTextMaxAngle().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextMaxAngle().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextMaxAngle().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextMaxAngle().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textMaxAngle(0.3f));
+ assertEquals((Float) layer.getTextMaxAngle().getValue(), (Float) 0.3f);
});
}
@@ -2531,229 +662,42 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textRotate(0.3f));
- assertEquals((Float) layer.getTextRotate().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextRotateAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textRotate(
- zoom(
- exponential(
- stop(2, textRotate(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextRotate());
- assertNotNull(layer.getTextRotate().getFunction());
- assertEquals(CameraFunction.class, layer.getTextRotate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextRotate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextRotate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextRotate().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textRotate(0.3f));
+ assertEquals((Float) layer.getTextRotate().getValue(), (Float) 0.3f);
});
}
@Test
- public void testTextRotateAsIdentitySourceFunction() {
+ public void testTextRotateAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("text-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textRotate(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextRotate());
- assertNotNull(layer.getTextRotate().getFunction());
- assertEquals(SourceFunction.class, layer.getTextRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextRotate().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextRotate().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("text-rotate-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextRotateAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textRotate(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, textRotate(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextRotate());
- assertNotNull(layer.getTextRotate().getFunction());
- assertEquals(SourceFunction.class, layer.getTextRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextRotate().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextRotate().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(textRotate(expression));
+ assertEquals(layer.getTextRotate().getExpression(), expression);
});
}
- @Test
- public void testTextRotateAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textRotate(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, textRotate(0.3f))
- )
- ).withDefaultValue(textRotate(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextRotate());
- assertNotNull(layer.getTextRotate().getFunction());
- assertEquals(SourceFunction.class, layer.getTextRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextRotate().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextRotate().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextRotate().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextRotate().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getTextRotate().getFunction()).getDefaultValue().getValue());
- }
- });
-
- }
-
- @Test
- public void testTextRotateAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-rotate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textRotate(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, textRotate(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(textRotate(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextRotate());
- assertNotNull(layer.getTextRotate().getFunction());
- assertEquals(CompositeFunction.class, layer.getTextRotate().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextRotate().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextRotate().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getTextRotate().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextRotate().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testTextPaddingAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("text-padding");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textPadding(0.3f));
- assertEquals((Float) layer.getTextPadding().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextPaddingAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-padding");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textPadding(
- zoom(
- exponential(
- stop(2, textPadding(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextPadding());
- assertNotNull(layer.getTextPadding().getFunction());
- assertEquals(CameraFunction.class, layer.getTextPadding().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextPadding().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextPadding().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextPadding().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textPadding(0.3f));
+ assertEquals((Float) layer.getTextPadding().getValue(), (Float) 0.3f);
});
}
@@ -2762,46 +706,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-keep-upright");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textKeepUpright(true));
- assertEquals((Boolean) layer.getTextKeepUpright().getValue(), (Boolean) true);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextKeepUprightAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-keep-upright");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textKeepUpright(
- zoom(
- interval(
- stop(2, textKeepUpright(true))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextKeepUpright());
- assertNotNull(layer.getTextKeepUpright().getFunction());
- assertEquals(CameraFunction.class, layer.getTextKeepUpright().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextKeepUpright().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextKeepUpright().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textKeepUpright(true));
+ assertEquals((Boolean) layer.getTextKeepUpright().getValue(), (Boolean) true);
});
}
@@ -2810,209 +720,42 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-transform");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textTransform(TEXT_TRANSFORM_NONE));
- assertEquals((String) layer.getTextTransform().getValue(), (String) TEXT_TRANSFORM_NONE);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextTransformAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-transform");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textTransform(
- zoom(
- interval(
- stop(2, textTransform(TEXT_TRANSFORM_NONE))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextTransform());
- assertNotNull(layer.getTextTransform().getFunction());
- assertEquals(CameraFunction.class, layer.getTextTransform().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextTransform().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextTransform().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textTransform(TEXT_TRANSFORM_NONE));
+ assertEquals((String) layer.getTextTransform().getValue(), (String) TEXT_TRANSFORM_NONE);
});
}
@Test
- public void testTextTransformAsIdentitySourceFunction() {
+ public void testTextTransformAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("text-transform");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textTransform(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextTransform());
- assertNotNull(layer.getTextTransform().getFunction());
- assertEquals(SourceFunction.class, layer.getTextTransform().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextTransform().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextTransform().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("text-transform-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextTransformAsIntervalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-transform");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textTransform(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, textTransform(TEXT_TRANSFORM_NONE))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextTransform());
- assertNotNull(layer.getTextTransform().getFunction());
- assertEquals(SourceFunction.class, layer.getTextTransform().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextTransform().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getTextTransform().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = string(Expression.get("undefined"));
+ layer.setProperties(textTransform(expression));
+ assertEquals(layer.getTextTransform().getExpression(), expression);
});
}
- @Test
- public void testTextOffsetAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- 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 testTextOffsetAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOffset(
- zoom(
- exponential(
- stop(2, textOffset(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextOffset());
- assertNotNull(layer.getTextOffset().getFunction());
- assertEquals(CameraFunction.class, layer.getTextOffset().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextOffset().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextOffset().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextOffset().getFunction().getStops()).size());
- }
- });
- }
-
- @Test
- public void testTextOffsetAsIdentitySourceFunction() {
+ public void testTextOffsetAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("text-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOffset(property("FeaturePropertyA", Stops.<Float[]>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextOffset());
- assertNotNull(layer.getTextOffset().getFunction());
- assertEquals(SourceFunction.class, layer.getTextOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOffset().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextOffset().getFunction().getStops().getClass());
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextOffsetAsIntervalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-offset");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOffset(
- property(
- "FeaturePropertyA",
- interval(
- stop(1, textOffset(new Float[] {0f, 0f}))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextOffset());
- assertNotNull(layer.getTextOffset().getFunction());
- assertEquals(SourceFunction.class, layer.getTextOffset().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOffset().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.getTextOffset().getFunction().getStops().getClass());
- }
+ // Set and Get
+ layer.setProperties(textOffset(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getTextOffset().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -3021,46 +764,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-allow-overlap");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textAllowOverlap(true));
- assertEquals((Boolean) layer.getTextAllowOverlap().getValue(), (Boolean) true);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextAllowOverlapAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-allow-overlap");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textAllowOverlap(
- zoom(
- interval(
- stop(2, textAllowOverlap(true))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextAllowOverlap());
- assertNotNull(layer.getTextAllowOverlap().getFunction());
- assertEquals(CameraFunction.class, layer.getTextAllowOverlap().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextAllowOverlap().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextAllowOverlap().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textAllowOverlap(true));
+ assertEquals((Boolean) layer.getTextAllowOverlap().getValue(), (Boolean) true);
});
}
@@ -3069,46 +778,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-ignore-placement");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textIgnorePlacement(true));
- assertEquals((Boolean) layer.getTextIgnorePlacement().getValue(), (Boolean) true);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextIgnorePlacementAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-ignore-placement");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textIgnorePlacement(
- zoom(
- interval(
- stop(2, textIgnorePlacement(true))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextIgnorePlacement());
- assertNotNull(layer.getTextIgnorePlacement().getFunction());
- assertEquals(CameraFunction.class, layer.getTextIgnorePlacement().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextIgnorePlacement().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextIgnorePlacement().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textIgnorePlacement(true));
+ assertEquals((Boolean) layer.getTextIgnorePlacement().getValue(), (Boolean) true);
});
}
@@ -3117,46 +792,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-optional");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textOptional(true));
- assertEquals((Boolean) layer.getTextOptional().getValue(), (Boolean) true);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextOptionalAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-optional");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOptional(
- zoom(
- interval(
- stop(2, textOptional(true))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextOptional());
- assertNotNull(layer.getTextOptional().getFunction());
- assertEquals(CameraFunction.class, layer.getTextOptional().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextOptional().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextOptional().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textOptional(true));
+ assertEquals((Boolean) layer.getTextOptional().getValue(), (Boolean) true);
});
}
@@ -3165,16 +806,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setIconOpacityTransition(options);
- assertEquals(layer.getIconOpacityTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconOpacityTransition(options);
+ assertEquals(layer.getIconOpacityTransition(), options);
});
}
@@ -3183,198 +821,43 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconOpacity(0.3f));
- assertEquals((Float) layer.getIconOpacity().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconOpacityAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOpacity(
- zoom(
- exponential(
- stop(2, iconOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconOpacity());
- assertNotNull(layer.getIconOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getIconOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconOpacity().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconOpacity(0.3f));
+ assertEquals((Float) layer.getIconOpacity().getValue(), (Float) 0.3f);
});
}
@Test
- public void testIconOpacityAsIdentitySourceFunction() {
+ public void testIconOpacityAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("icon-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconOpacity());
- assertNotNull(layer.getIconOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getIconOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOpacity().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("icon-opacity-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconOpacityAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOpacity(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, iconOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconOpacity());
- assertNotNull(layer.getIconOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getIconOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(iconOpacity(expression));
+ assertEquals(layer.getIconOpacity().getExpression(), expression);
});
}
- @Test
- public void testIconOpacityAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOpacity(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, iconOpacity(0.3f))
- )
- ).withDefaultValue(iconOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconOpacity());
- assertNotNull(layer.getIconOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getIconOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconOpacity().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getIconOpacity().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getIconOpacity().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getIconOpacity().getFunction()).getDefaultValue().getValue());
- }
- });
-
- }
-
- @Test
- public void testIconOpacityAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconOpacity(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, iconOpacity(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(iconOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconOpacity());
- assertNotNull(layer.getIconOpacity().getFunction());
- assertEquals(CompositeFunction.class, layer.getIconOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconOpacity().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getIconOpacity().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconOpacity().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testIconColorTransition() {
validateTestSetup();
setupLayer();
Timber.i("icon-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setIconColorTransition(options);
- assertEquals(layer.getIconColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconColorTransition(options);
+ assertEquals(layer.getIconColorTransition(), options);
});
}
@@ -3383,157 +866,42 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getIconColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconColorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconColor(
- zoom(
- exponential(
- stop(2, iconColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconColor());
- assertNotNull(layer.getIconColor().getFunction());
- assertEquals(CameraFunction.class, layer.getIconColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconColor().getFunction().getStops()).size());
- }
+ // 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 testIconColorAsIdentitySourceFunction() {
+ public void testIconColorAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("icon-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconColor());
- assertNotNull(layer.getIconColor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconColor().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("icon-color-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconColorAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, iconColor(Color.RED))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconColor());
- assertNotNull(layer.getIconColor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconColor().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(iconColor(expression));
+ assertEquals(layer.getIconColor().getExpression(), expression);
});
}
- @Test
- public void testIconColorAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", iconColor(Color.RED))
- )
- ).withDefaultValue(iconColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconColor());
- assertNotNull(layer.getIconColor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getIconColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getIconColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getIconColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getIconColor().getFunction()).getDefaultValue().getColorInt());
- }
- });
-
- }
@Test
public void testIconColorAsIntConstant() {
validateTestSetup();
setupLayer();
Timber.i("icon-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconColor(Color.RED));
- assertEquals(layer.getIconColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconColor(Color.RED));
+ assertEquals(layer.getIconColorAsInt(), Color.RED);
});
}
@@ -3542,16 +910,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setIconHaloColorTransition(options);
- assertEquals(layer.getIconHaloColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconHaloColorTransition(options);
+ assertEquals(layer.getIconHaloColorTransition(), options);
});
}
@@ -3560,157 +925,42 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconHaloColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getIconHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconHaloColorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloColor(
- zoom(
- exponential(
- stop(2, iconHaloColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloColor());
- assertNotNull(layer.getIconHaloColor().getFunction());
- assertEquals(CameraFunction.class, layer.getIconHaloColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconHaloColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconHaloColor().getFunction().getStops()).size());
- }
+ // 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 testIconHaloColorAsIdentitySourceFunction() {
+ public void testIconHaloColorAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("icon-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconHaloColor());
- assertNotNull(layer.getIconHaloColor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("icon-halo-color-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconHaloColorAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, iconHaloColor(Color.RED))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloColor());
- assertNotNull(layer.getIconHaloColor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(iconHaloColor(expression));
+ assertEquals(layer.getIconHaloColor().getExpression(), expression);
});
}
- @Test
- public void testIconHaloColorAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", iconHaloColor(Color.RED))
- )
- ).withDefaultValue(iconHaloColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloColor());
- assertNotNull(layer.getIconHaloColor().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getIconHaloColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getIconHaloColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getIconHaloColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getIconHaloColor().getFunction()).getDefaultValue().getColorInt());
- }
- });
-
- }
@Test
public void testIconHaloColorAsIntConstant() {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconHaloColor(Color.RED));
- assertEquals(layer.getIconHaloColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(iconHaloColor(Color.RED));
+ assertEquals(layer.getIconHaloColorAsInt(), Color.RED);
});
}
@@ -3719,16 +969,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-widthTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setIconHaloWidthTransition(options);
- assertEquals(layer.getIconHaloWidthTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconHaloWidthTransition(options);
+ assertEquals(layer.getIconHaloWidthTransition(), options);
});
}
@@ -3737,398 +984,88 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconHaloWidth(0.3f));
- assertEquals((Float) layer.getIconHaloWidth().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconHaloWidthAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloWidth(
- zoom(
- exponential(
- stop(2, iconHaloWidth(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloWidth());
- assertNotNull(layer.getIconHaloWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getIconHaloWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconHaloWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconHaloWidth().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconHaloWidth(0.3f));
+ assertEquals((Float) layer.getIconHaloWidth().getValue(), (Float) 0.3f);
});
}
@Test
- public void testIconHaloWidthAsIdentitySourceFunction() {
+ public void testIconHaloWidthAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("icon-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloWidth(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconHaloWidth());
- assertNotNull(layer.getIconHaloWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloWidth().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("icon-halo-width-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconHaloWidthAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloWidth(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, iconHaloWidth(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloWidth());
- assertNotNull(layer.getIconHaloWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
- }
- });
- }
-
- @Test
- public void testIconHaloWidthAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloWidth(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, iconHaloWidth(0.3f))
- )
- ).withDefaultValue(iconHaloWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloWidth());
- assertNotNull(layer.getIconHaloWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloWidth().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getIconHaloWidth().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getIconHaloWidth().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getIconHaloWidth().getFunction()).getDefaultValue().getValue());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(iconHaloWidth(expression));
+ assertEquals(layer.getIconHaloWidth().getExpression(), expression);
});
-
}
- @Test
- public void testIconHaloWidthAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloWidth(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, iconHaloWidth(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(iconHaloWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloWidth());
- assertNotNull(layer.getIconHaloWidth().getFunction());
- assertEquals(CompositeFunction.class, layer.getIconHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconHaloWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconHaloWidth().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getIconHaloWidth().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconHaloWidth().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testIconHaloBlurTransition() {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-blurTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setIconHaloBlurTransition(options);
- assertEquals(layer.getIconHaloBlurTransition(), options);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconHaloBlurAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconHaloBlur(0.3f));
- assertEquals((Float) layer.getIconHaloBlur().getValue(), (Float) 0.3f);
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconHaloBlurTransition(options);
+ assertEquals(layer.getIconHaloBlurTransition(), options);
});
}
@Test
- public void testIconHaloBlurAsCameraFunction() {
+ public void testIconHaloBlurAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("icon-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloBlur(
- zoom(
- exponential(
- stop(2, iconHaloBlur(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloBlur());
- assertNotNull(layer.getIconHaloBlur().getFunction());
- assertEquals(CameraFunction.class, layer.getIconHaloBlur().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconHaloBlur().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconHaloBlur().getFunction().getStops()).size());
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconHaloBlurAsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloBlur(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getIconHaloBlur());
- assertNotNull(layer.getIconHaloBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloBlur().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
- }
+ // Set and Get
+ layer.setProperties(iconHaloBlur(0.3f));
+ assertEquals((Float) layer.getIconHaloBlur().getValue(), (Float) 0.3f);
});
}
@Test
- public void testIconHaloBlurAsExponentialSourceFunction() {
+ public void testIconHaloBlurAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("icon-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloBlur(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, iconHaloBlur(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloBlur());
- assertNotNull(layer.getIconHaloBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("icon-halo-blur-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconHaloBlurAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloBlur(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, iconHaloBlur(0.3f))
- )
- ).withDefaultValue(iconHaloBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloBlur());
- assertNotNull(layer.getIconHaloBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getIconHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getIconHaloBlur().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getIconHaloBlur().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getIconHaloBlur().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getIconHaloBlur().getFunction()).getDefaultValue().getValue());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(iconHaloBlur(expression));
+ assertEquals(layer.getIconHaloBlur().getExpression(), expression);
});
-
}
- @Test
- public void testIconHaloBlurAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconHaloBlur(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, iconHaloBlur(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(iconHaloBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getIconHaloBlur());
- assertNotNull(layer.getIconHaloBlur().getFunction());
- assertEquals(CompositeFunction.class, layer.getIconHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getIconHaloBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getIconHaloBlur().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getIconHaloBlur().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getIconHaloBlur().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testIconTranslateTransition() {
validateTestSetup();
setupLayer();
Timber.i("icon-translateTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setIconTranslateTransition(options);
- assertEquals(layer.getIconTranslateTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setIconTranslateTransition(options);
+ assertEquals(layer.getIconTranslateTransition(), options);
});
}
@@ -4137,47 +1074,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconTranslate(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getIconTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconTranslateAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconTranslate(
- zoom(
- exponential(
- stop(2, iconTranslate(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconTranslate());
- assertNotNull(layer.getIconTranslate().getFunction());
- assertEquals(CameraFunction.class, layer.getIconTranslate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getIconTranslate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getIconTranslate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getIconTranslate().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getIconTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -4186,46 +1088,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("icon-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(iconTranslateAnchor(ICON_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getIconTranslateAnchor().getValue(), (String) ICON_TRANSLATE_ANCHOR_MAP);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testIconTranslateAnchorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("icon-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- iconTranslateAnchor(
- zoom(
- interval(
- stop(2, iconTranslateAnchor(ICON_TRANSLATE_ANCHOR_MAP))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getIconTranslateAnchor());
- assertNotNull(layer.getIconTranslateAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getIconTranslateAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getIconTranslateAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getIconTranslateAnchor().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(iconTranslateAnchor(ICON_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getIconTranslateAnchor().getValue(), (String) ICON_TRANSLATE_ANCHOR_MAP);
});
}
@@ -4234,216 +1102,58 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-opacityTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setTextOpacityTransition(options);
- assertEquals(layer.getTextOpacityTransition(), options);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextOpacityAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textOpacity(0.3f));
- assertEquals((Float) layer.getTextOpacity().getValue(), (Float) 0.3f);
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextOpacityTransition(options);
+ assertEquals(layer.getTextOpacityTransition(), options);
});
}
@Test
- public void testTextOpacityAsCameraFunction() {
+ public void testTextOpacityAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("text-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOpacity(
- zoom(
- exponential(
- stop(2, textOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextOpacity());
- assertNotNull(layer.getTextOpacity().getFunction());
- assertEquals(CameraFunction.class, layer.getTextOpacity().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextOpacity().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextOpacity().getFunction().getStops()).size());
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextOpacityAsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOpacity(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextOpacity());
- assertNotNull(layer.getTextOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getTextOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOpacity().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
- }
+ // Set and Get
+ layer.setProperties(textOpacity(0.3f));
+ assertEquals((Float) layer.getTextOpacity().getValue(), (Float) 0.3f);
});
}
@Test
- public void testTextOpacityAsExponentialSourceFunction() {
+ public void testTextOpacityAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("text-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOpacity(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, textOpacity(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextOpacity());
- assertNotNull(layer.getTextOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getTextOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("text-opacity-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextOpacityAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOpacity(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, textOpacity(0.3f))
- )
- ).withDefaultValue(textOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextOpacity());
- assertNotNull(layer.getTextOpacity().getFunction());
- assertEquals(SourceFunction.class, layer.getTextOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextOpacity().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextOpacity().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextOpacity().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getTextOpacity().getFunction()).getDefaultValue().getValue());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(textOpacity(expression));
+ assertEquals(layer.getTextOpacity().getExpression(), expression);
});
-
}
- @Test
- public void testTextOpacityAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-opacity");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textOpacity(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, textOpacity(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(textOpacity(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextOpacity());
- assertNotNull(layer.getTextOpacity().getFunction());
- assertEquals(CompositeFunction.class, layer.getTextOpacity().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextOpacity().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextOpacity().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getTextOpacity().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextOpacity().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testTextColorTransition() {
validateTestSetup();
setupLayer();
Timber.i("text-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setTextColorTransition(options);
- assertEquals(layer.getTextColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextColorTransition(options);
+ assertEquals(layer.getTextColorTransition(), options);
});
}
@@ -4452,157 +1162,42 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getTextColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextColorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textColor(
- zoom(
- exponential(
- stop(2, textColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextColor());
- assertNotNull(layer.getTextColor().getFunction());
- assertEquals(CameraFunction.class, layer.getTextColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextColor().getFunction().getStops()).size());
- }
+ // 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 testTextColorAsIdentitySourceFunction() {
+ public void testTextColorAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("text-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextColor());
- assertNotNull(layer.getTextColor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextColor().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("text-color-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextColorAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, textColor(Color.RED))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextColor());
- assertNotNull(layer.getTextColor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextColor().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(textColor(expression));
+ assertEquals(layer.getTextColor().getExpression(), expression);
});
}
- @Test
- public void testTextColorAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", textColor(Color.RED))
- )
- ).withDefaultValue(textColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextColor());
- assertNotNull(layer.getTextColor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getTextColor().getFunction()).getDefaultValue().getColorInt());
- }
- });
-
- }
@Test
public void testTextColorAsIntConstant() {
validateTestSetup();
setupLayer();
Timber.i("text-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textColor(Color.RED));
- assertEquals(layer.getTextColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textColor(Color.RED));
+ assertEquals(layer.getTextColorAsInt(), Color.RED);
});
}
@@ -4611,16 +1206,13 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-colorTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setTextHaloColorTransition(options);
- assertEquals(layer.getTextHaloColorTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextHaloColorTransition(options);
+ assertEquals(layer.getTextHaloColorTransition(), options);
});
}
@@ -4629,157 +1221,42 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textHaloColor("rgba(0, 0, 0, 1)"));
- assertEquals((String) layer.getTextHaloColor().getValue(), (String) "rgba(0, 0, 0, 1)");
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextHaloColorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloColor(
- zoom(
- exponential(
- stop(2, textHaloColor("rgba(0, 0, 0, 1)"))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloColor());
- assertNotNull(layer.getTextHaloColor().getFunction());
- assertEquals(CameraFunction.class, layer.getTextHaloColor().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextHaloColor().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextHaloColor().getFunction().getStops()).size());
- }
+ // 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 testTextHaloColorAsIdentitySourceFunction() {
+ public void testTextHaloColorAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("text-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloColor(property("FeaturePropertyA", Stops.<String>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextHaloColor());
- assertNotNull(layer.getTextHaloColor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloColor().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("text-halo-color-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextHaloColorAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloColor(
- property(
- "FeaturePropertyA",
- exponential(
- stop(Color.RED, textHaloColor(Color.RED))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloColor());
- assertNotNull(layer.getTextHaloColor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloColor().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = toColor(Expression.get("undefined"));
+ layer.setProperties(textHaloColor(expression));
+ assertEquals(layer.getTextHaloColor().getExpression(), expression);
});
}
- @Test
- public void testTextHaloColorAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloColor(
- property(
- "FeaturePropertyA",
- categorical(
- stop("valueA", textHaloColor(Color.RED))
- )
- ).withDefaultValue(textHaloColor(Color.GREEN))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloColor());
- assertNotNull(layer.getTextHaloColor().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloColor().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloColor().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextHaloColor().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextHaloColor().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextHaloColor().getFunction()).getDefaultValue().getValue());
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.getTextHaloColor().getFunction()).getDefaultValue().getColorInt());
- }
- });
-
- }
@Test
public void testTextHaloColorAsIntConstant() {
validateTestSetup();
setupLayer();
Timber.i("text-halo-color");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textHaloColor(Color.RED));
- assertEquals(layer.getTextHaloColorAsInt(), Color.RED);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ layer.setProperties(textHaloColor(Color.RED));
+ assertEquals(layer.getTextHaloColorAsInt(), Color.RED);
});
}
@@ -4788,216 +1265,58 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-widthTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setTextHaloWidthTransition(options);
- assertEquals(layer.getTextHaloWidthTransition(), options);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextHaloWidthAsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textHaloWidth(0.3f));
- assertEquals((Float) layer.getTextHaloWidth().getValue(), (Float) 0.3f);
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextHaloWidthTransition(options);
+ assertEquals(layer.getTextHaloWidthTransition(), options);
});
}
@Test
- public void testTextHaloWidthAsCameraFunction() {
+ public void testTextHaloWidthAsConstant() {
validateTestSetup();
setupLayer();
Timber.i("text-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloWidth(
- zoom(
- exponential(
- stop(2, textHaloWidth(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloWidth());
- assertNotNull(layer.getTextHaloWidth().getFunction());
- assertEquals(CameraFunction.class, layer.getTextHaloWidth().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextHaloWidth().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextHaloWidth().getFunction().getStops()).size());
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextHaloWidthAsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloWidth(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextHaloWidth());
- assertNotNull(layer.getTextHaloWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloWidth().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
- }
+ // Set and Get
+ layer.setProperties(textHaloWidth(0.3f));
+ assertEquals((Float) layer.getTextHaloWidth().getValue(), (Float) 0.3f);
});
}
@Test
- public void testTextHaloWidthAsExponentialSourceFunction() {
+ public void testTextHaloWidthAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("text-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloWidth(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, textHaloWidth(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloWidth());
- assertNotNull(layer.getTextHaloWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("text-halo-width-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextHaloWidthAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloWidth(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, textHaloWidth(0.3f))
- )
- ).withDefaultValue(textHaloWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloWidth());
- assertNotNull(layer.getTextHaloWidth().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloWidth().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextHaloWidth().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextHaloWidth().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getTextHaloWidth().getFunction()).getDefaultValue().getValue());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(textHaloWidth(expression));
+ assertEquals(layer.getTextHaloWidth().getExpression(), expression);
});
-
}
- @Test
- public void testTextHaloWidthAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-halo-width");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloWidth(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, textHaloWidth(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(textHaloWidth(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloWidth());
- assertNotNull(layer.getTextHaloWidth().getFunction());
- assertEquals(CompositeFunction.class, layer.getTextHaloWidth().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextHaloWidth().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextHaloWidth().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getTextHaloWidth().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextHaloWidth().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testTextHaloBlurTransition() {
validateTestSetup();
setupLayer();
Timber.i("text-halo-blurTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setTextHaloBlurTransition(options);
- assertEquals(layer.getTextHaloBlurTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextHaloBlurTransition(options);
+ assertEquals(layer.getTextHaloBlurTransition(), options);
});
}
@@ -5006,198 +1325,43 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textHaloBlur(0.3f));
- assertEquals((Float) layer.getTextHaloBlur().getValue(), (Float) 0.3f);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextHaloBlurAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloBlur(
- zoom(
- exponential(
- stop(2, textHaloBlur(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloBlur());
- assertNotNull(layer.getTextHaloBlur().getFunction());
- assertEquals(CameraFunction.class, layer.getTextHaloBlur().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextHaloBlur().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextHaloBlur().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textHaloBlur(0.3f));
+ assertEquals((Float) layer.getTextHaloBlur().getValue(), (Float) 0.3f);
});
}
@Test
- public void testTextHaloBlurAsIdentitySourceFunction() {
+ public void testTextHaloBlurAsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("text-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloBlur(property("FeaturePropertyA", Stops.<Float>identity()))
- );
-
- // Verify
- assertNotNull(layer.getTextHaloBlur());
- assertNotNull(layer.getTextHaloBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloBlur().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
- }
- });
- }
+ Timber.i("text-halo-blur-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextHaloBlurAsExponentialSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloBlur(
- property(
- "FeaturePropertyA",
- exponential(
- stop(0.3f, textHaloBlur(0.3f))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloBlur());
- assertNotNull(layer.getTextHaloBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
- }
+ // Set and Get
+ Expression expression = number(Expression.get("undefined"));
+ layer.setProperties(textHaloBlur(expression));
+ assertEquals(layer.getTextHaloBlur().getExpression(), expression);
});
}
- @Test
- public void testTextHaloBlurAsCategoricalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloBlur(
- property(
- "FeaturePropertyA",
- categorical(
- stop(1.0f, textHaloBlur(0.3f))
- )
- ).withDefaultValue(textHaloBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloBlur());
- assertNotNull(layer.getTextHaloBlur().getFunction());
- assertEquals(SourceFunction.class, layer.getTextHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.getTextHaloBlur().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.getTextHaloBlur().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.getTextHaloBlur().getFunction()).getDefaultValue().getValue());
- assertEquals(0.3f, ((SourceFunction) layer.getTextHaloBlur().getFunction()).getDefaultValue().getValue());
- }
- });
-
- }
-
- @Test
- public void testTextHaloBlurAsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-halo-blur");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textHaloBlur(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, textHaloBlur(0.9f))
- ).withBase(0.5f)
- ).withDefaultValue(textHaloBlur(0.3f))
- )
- );
-
- // Verify
- assertNotNull(layer.getTextHaloBlur());
- assertNotNull(layer.getTextHaloBlur().getFunction());
- assertEquals(CompositeFunction.class, layer.getTextHaloBlur().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.getTextHaloBlur().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.getTextHaloBlur().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.getTextHaloBlur().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, Float>, Float> stops =
- (ExponentialStops<Stop.CompositeValue<Float, Float>, Float>) layer.getTextHaloBlur().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, Float>, Float> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
@Test
public void testTextTranslateTransition() {
validateTestSetup();
setupLayer();
Timber.i("text-translateTransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.setTextTranslateTransition(options);
- assertEquals(layer.getTextTranslateTransition(), options);
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.setTextTranslateTransition(options);
+ assertEquals(layer.getTextTranslateTransition(), options);
});
}
@@ -5206,47 +1370,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textTranslate(new Float[] {0f, 0f}));
- assertEquals((Float[]) layer.getTextTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextTranslateAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-translate");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textTranslate(
- zoom(
- exponential(
- stop(2, textTranslate(new Float[] {0f, 0f}))
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextTranslate());
- assertNotNull(layer.getTextTranslate().getFunction());
- assertEquals(CameraFunction.class, layer.getTextTranslate().getFunction().getClass());
- assertEquals(ExponentialStops.class, layer.getTextTranslate().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.getTextTranslate().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.getTextTranslate().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textTranslate(new Float[] {0f, 0f}));
+ assertEquals((Float[]) layer.getTextTranslate().getValue(), (Float[]) new Float[] {0f, 0f});
});
}
@@ -5255,47 +1384,12 @@ public class SymbolLayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("text-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(textTranslateAnchor(TEXT_TRANSLATE_ANCHOR_MAP));
- assertEquals((String) layer.getTextTranslateAnchor().getValue(), (String) TEXT_TRANSLATE_ANCHOR_MAP);
- }
- });
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- @Test
- public void testTextTranslateAnchorAsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("text-translate-anchor");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- textTranslateAnchor(
- zoom(
- interval(
- stop(2, textTranslateAnchor(TEXT_TRANSLATE_ANCHOR_MAP))
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.getTextTranslateAnchor());
- assertNotNull(layer.getTextTranslateAnchor().getFunction());
- assertEquals(CameraFunction.class, layer.getTextTranslateAnchor().getFunction().getClass());
- assertEquals(IntervalStops.class, layer.getTextTranslateAnchor().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.getTextTranslateAnchor().getFunction().getStops()).size());
- }
+ // Set and Get
+ layer.setProperties(textTranslateAnchor(TEXT_TRANSLATE_ANCHOR_MAP));
+ assertEquals((String) layer.getTextTranslateAnchor().getValue(), (String) TEXT_TRANSLATE_ANCHOR_MAP);
});
}
-
-}
+} \ No newline at end of file
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 206497b860..935813899f 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
@@ -7,31 +7,18 @@
package com.mapbox.mapboxsdk.testapp.style;
import android.graphics.Color;
-import android.support.test.espresso.UiController;
import android.support.test.runner.AndroidJUnit4;
import timber.log.Timber;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.CompositeFunction;
-import com.mapbox.mapboxsdk.style.functions.CameraFunction;
-import com.mapbox.mapboxsdk.style.functions.SourceFunction;
-import com.mapbox.mapboxsdk.style.functions.stops.CategoricalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.ExponentialStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
-import com.mapbox.mapboxsdk.style.functions.stops.IntervalStops;
-import com.mapbox.mapboxsdk.style.functions.stops.Stop;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.<%- camelize(type) %>Layer;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import org.junit.Test;
import org.junit.runner.RunWith;
-import static com.mapbox.mapboxsdk.style.functions.Function.*;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.*;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.*;
import static com.mapbox.mapboxsdk.testapp.action.MapboxMapAction.invoke;
import static org.junit.Assert.*;
import static com.mapbox.mapboxsdk.style.layers.Property.*;
@@ -56,25 +43,19 @@ public class <%- camelize(type) %>LayerTest extends BaseActivityTest {
private void setupLayer() {
<% if (type === 'background') { -%>
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- layer = mapboxMap.getLayerAs("background");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ layer = mapboxMap.getLayerAs("background");
});
<% } else { -%>
Timber.i("Retrieving layer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
- Timber.i("Adding layer");
- layer = new <%- camelize(type) %>Layer("my-layer", "composite");
- layer.setSourceLayer("composite");
- mapboxMap.addLayer(layer);
- // Layer reference is now stale, get new reference
- layer = mapboxMap.getLayerAs("my-layer");
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ if ((layer = mapboxMap.getLayerAs("my-layer")) == null) {
+ Timber.i("Adding layer");
+ layer = new <%- camelize(type) %>Layer("my-layer", "composite");
+ layer.setSourceLayer("composite");
+ mapboxMap.addLayer(layer);
+ // Layer reference is now stale, get new reference
+ layer = mapboxMap.getLayerAs("my-layer");
}
});
<% } -%>
@@ -85,18 +66,15 @@ public class <%- camelize(type) %>LayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("Visibility");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ 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);
});
}
<% if (!(type === 'background' || type === 'raster' || type === 'hillshade')) { -%>
@@ -106,334 +84,90 @@ public class <%- camelize(type) %>LayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("SourceLayer");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Get initial
- assertEquals(layer.getSourceLayer(), "composite");
+ // Get initial
+ assertEquals(layer.getSourceLayer(), "composite");
- // Set
- final String sourceLayer = "test";
- layer.setSourceLayer(sourceLayer);
- assertEquals(layer.getSourceLayer(), sourceLayer);
- }
+ // Set
+ final String sourceLayer = "test";
+ layer.setSourceLayer(sourceLayer);
+ assertEquals(layer.getSourceLayer(), sourceLayer);
});
}
-<% } -%>
-<% for (const property of properties) { -%>
-<% if (property.transition) { -%>
@Test
- public void test<%- camelize(property.name) %>Transition() {
+ public void testFilter() {
validateTestSetup();
setupLayer();
- Timber.i("<%- property.name %>TransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ Timber.i("Filter");
+ invoke(mapboxMap, (uiController, mapboxMap1) -> {
+ assertNotNull(layer);
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- layer.set<%- camelize(property.name) %>Transition(options);
- assertEquals(layer.get<%- camelize(property.name) %>Transition(), options);
- }
- });
- }
-<% } -%>
+ // Get initial
+ assertEquals(layer.getFilter(), null);
- @Test
- public void test<%- camelize(property.name) %>AsConstant() {
- validateTestSetup();
- setupLayer();
- Timber.i("<%- property.name %>");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set and Get
- layer.setProperties(<%- camelizeWithLeadingLowercase(property.name) %>(<%- defaultValueJava(property) %>));
- assertEquals((<%- propertyType(property) %>) layer.get<%- camelize(property.name) %>().getValue(), (<%- propertyType(property) %>) <%- defaultValueJava(property) %>);
- }
+ // Set
+ Expression filter = eq(get("undefined"), literal(1.0));
+ layer.setFilter(filter);
+ assertEquals(layer.getFilter().toString(), filter.toString());
});
}
-<% if (supportsZoomFunction(property)) { -%>
-
- @Test
- public void test<%- camelize(property.name) %>AsCameraFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("<%- property.name %>");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
- // Set
- layer.setProperties(
- <%- camelizeWithLeadingLowercase(property.name) %>(
- zoom(
-<% if (property.function == 'piecewise-constant') { -%>
- interval(
- stop(2, <%- camelizeWithLeadingLowercase(property.name) %>(<%- defaultValueJava(property) %>))
- )
-<% } else { -%>
- exponential(
- stop(2, <%- camelizeWithLeadingLowercase(property.name) %>(<%- defaultValueJava(property) %>))
- ).withBase(0.5f)
-<% } -%>
- )
- )
- );
- // Verify
- assertNotNull(layer.get<%- camelize(property.name) %>());
- assertNotNull(layer.get<%- camelize(property.name) %>().getFunction());
- assertEquals(CameraFunction.class, layer.get<%- camelize(property.name) %>().getFunction().getClass());
-<% if (property.function == 'piecewise-constant') { -%>
- assertEquals(IntervalStops.class, layer.get<%- camelize(property.name) %>().getFunction().getStops().getClass());
- assertEquals(1, ((IntervalStops) layer.get<%- camelize(property.name) %>().getFunction().getStops()).size());
-<% } else { -%>
- assertEquals(ExponentialStops.class, layer.get<%- camelize(property.name) %>().getFunction().getStops().getClass());
- assertEquals(0.5f, ((ExponentialStops) layer.get<%- camelize(property.name) %>().getFunction().getStops()).getBase(), 0.001);
- assertEquals(1, ((ExponentialStops) layer.get<%- camelize(property.name) %>().getFunction().getStops()).size());
-<% } -%>
- }
- });
- }
<% } -%>
-<% if (supportsPropertyFunction(property)) { -%>
-
- @Test
- public void test<%- camelize(property.name) %>AsIdentitySourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("<%- property.name %>");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- <%- camelizeWithLeadingLowercase(property.name) %>(property("FeaturePropertyA", Stops.<<%- propertyType(property) %>>identity()))
- );
-
- // Verify
- assertNotNull(layer.get<%- camelize(property.name) %>());
- assertNotNull(layer.get<%- camelize(property.name) %>().getFunction());
- assertEquals(SourceFunction.class, layer.get<%- camelize(property.name) %>().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getProperty());
- assertEquals(IdentityStops.class, layer.get<%- camelize(property.name) %>().getFunction().getStops().getClass());
- }
- });
- }
-<% if (property.function == 'piecewise-constant') { -%>
+<% for (const property of properties) { -%>
+<% if (property.name != 'heatmap-color') { -%>
+<% if (property.transition) { -%>
@Test
- public void test<%- camelize(property.name) %>AsIntervalSourceFunction() {
+ public void test<%- camelize(property.name) %>Transition() {
validateTestSetup();
setupLayer();
- Timber.i("<%- property.name %>");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- <%- camelizeWithLeadingLowercase(property.name) %>(
- property(
- "FeaturePropertyA",
- interval(
-<% if (property.type == 'color') { -%>
- stop(Color.RED, <%- camelizeWithLeadingLowercase(property.name) %>(Color.RED))
-<% } else {-%>
- stop(1, <%- camelizeWithLeadingLowercase(property.name) %>(<%- defaultValueJava(property) %>))
- )
-<% } -%>
- )
- )
- );
+ Timber.i("<%- property.name %>TransitionOptions");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Verify
- assertNotNull(layer.get<%- camelize(property.name) %>());
- assertNotNull(layer.get<%- camelize(property.name) %>().getFunction());
- assertEquals(SourceFunction.class, layer.get<%- camelize(property.name) %>().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.get<%- camelize(property.name) %>().getFunction().getStops().getClass());
- }
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ layer.set<%- camelize(property.name) %>Transition(options);
+ assertEquals(layer.get<%- camelize(property.name) %>Transition(), options);
});
}
-<% } else if (property.type === 'array') { -%>
-
- @Test
- public void test<%- camelize(property.name) %>AsIntervalSourceFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("<%- property.name %>");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- <%- camelizeWithLeadingLowercase(property.name) %>(
- property(
- "FeaturePropertyA",
- interval(
-<% if (property.type == 'color') { -%>
- stop(Color.RED, <%- camelizeWithLeadingLowercase(property.name) %>(Color.RED))
-<% } else {-%>
- stop(1, <%- camelizeWithLeadingLowercase(property.name) %>(<%- defaultValueJava(property) %>))
<% } -%>
- )
- )
- )
- );
-
- // Verify
- assertNotNull(layer.get<%- camelize(property.name) %>());
- assertNotNull(layer.get<%- camelize(property.name) %>().getFunction());
- assertEquals(SourceFunction.class, layer.get<%- camelize(property.name) %>().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getProperty());
- assertEquals(IntervalStops.class, layer.get<%- camelize(property.name) %>().getFunction().getStops().getClass());
- }
- });
- }
-<% } else { -%>
@Test
- public void test<%- camelize(property.name) %>AsExponentialSourceFunction() {
+ public void test<%- camelize(property.name) %>AsConstant() {
validateTestSetup();
setupLayer();
Timber.i("<%- property.name %>");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Set
- layer.setProperties(
- <%- camelizeWithLeadingLowercase(property.name) %>(
- property(
- "FeaturePropertyA",
- exponential(
-<% if (property.type == 'color') { -%>
- stop(Color.RED, <%- camelizeWithLeadingLowercase(property.name) %>(Color.RED))
-<% } else {-%>
- stop(<%- defaultValueJava(property) %>, <%- camelizeWithLeadingLowercase(property.name) %>(<%- defaultValueJava(property) %>))
-<% } -%>
- ).withBase(0.5f)
- )
- )
- );
-
- // Verify
- assertNotNull(layer.get<%- camelize(property.name) %>());
- assertNotNull(layer.get<%- camelize(property.name) %>().getFunction());
- assertEquals(SourceFunction.class, layer.get<%- camelize(property.name) %>().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.get<%- camelize(property.name) %>().getFunction().getStops().getClass());
- }
+ // Set and Get
+ layer.setProperties(<%- camelizeWithLeadingLowercase(property.name) %>(<%- defaultValueJava(property) %>));
+ assertEquals((<%- propertyType(property) %>) layer.get<%- camelize(property.name) %>().getValue(), (<%- propertyType(property) %>) <%- defaultValueJava(property) %>);
});
}
+<% if (isDataDriven(property)) { -%>
+<% if (!(property.name.endsWith("-font")||property.name.endsWith("-offset"))) { -%>
@Test
- public void test<%- camelize(property.name) %>AsCategoricalSourceFunction() {
+ public void test<%- camelize(property.name) %>AsExpression() {
validateTestSetup();
setupLayer();
- Timber.i("<%- property.name %>");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
-
- // Set
- layer.setProperties(
- <%- camelizeWithLeadingLowercase(property.name) %>(
- property(
- "FeaturePropertyA",
- categorical(
-<% if (property.type == 'color') { -%>
- stop("valueA", <%- camelizeWithLeadingLowercase(property.name) %>(Color.RED))
- )
- ).withDefaultValue(<%- camelizeWithLeadingLowercase(property.name) %>(Color.GREEN))
-<% } else {-%>
- stop(1.0f, <%- camelizeWithLeadingLowercase(property.name) %>(<%- defaultValueJava(property) %>))
- )
- ).withDefaultValue(<%- camelizeWithLeadingLowercase(property.name) %>(<%- defaultValueJava(property) %>))
-<% } -%>
- )
- );
-
- // Verify
- assertNotNull(layer.get<%- camelize(property.name) %>());
- assertNotNull(layer.get<%- camelize(property.name) %>().getFunction());
- assertEquals(SourceFunction.class, layer.get<%- camelize(property.name) %>().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getProperty());
- assertEquals(CategoricalStops.class, layer.get<%- camelize(property.name) %>().getFunction().getStops().getClass());
- assertNotNull(((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getDefaultValue());
- assertNotNull(((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getDefaultValue().getValue());
-<% if (property.type === 'color') { -%>
- assertEquals(Color.GREEN, (int) ((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getDefaultValue().getColorInt());
-<% } else { -%>
- assertEquals(<%- defaultValueJava(property) %>, ((SourceFunction) layer.get<%- camelize(property.name) %>().getFunction()).getDefaultValue().getValue());
-<% } -%>
- }
+ Timber.i("<%- property.name %>-expression");
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
+
+ // Set and Get
+ Expression expression = <%- defaultExpressionJava(property) %>(Expression.get("undefined"));
+ layer.setProperties(<%- camelizeWithLeadingLowercase(property.name) %>(expression));
+ assertEquals(layer.get<%- camelize(property.name) %>().getExpression(), expression);
});
-
}
-<% if (property.type !== 'color') { -%>
-
- @Test
- public void test<%- camelize(property.name) %>AsCompositeFunction() {
- validateTestSetup();
- setupLayer();
- Timber.i("<%- property.name %>");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
- // Set
- layer.setProperties(
- <%- camelizeWithLeadingLowercase(property.name) %>(
- composite(
- "FeaturePropertyA",
- exponential(
- stop(0, 0.3f, <%- camelizeWithLeadingLowercase(property.name) %>(0.9f))
- ).withBase(0.5f)
-<% if (property.type == 'number') { -%>
- ).withDefaultValue(<%- camelizeWithLeadingLowercase(property.name) %>(<%- defaultValueJava(property) %>))
-<% } else { -%>
- )
-<% } -%>
- )
- );
-
- // Verify
- assertNotNull(layer.get<%- camelize(property.name) %>());
- assertNotNull(layer.get<%- camelize(property.name) %>().getFunction());
- assertEquals(CompositeFunction.class, layer.get<%- camelize(property.name) %>().getFunction().getClass());
- assertEquals("FeaturePropertyA", ((CompositeFunction) layer.get<%- camelize(property.name) %>().getFunction()).getProperty());
- assertEquals(ExponentialStops.class, layer.get<%- camelize(property.name) %>().getFunction().getStops().getClass());
- assertEquals(1, ((ExponentialStops) layer.get<%- camelize(property.name) %>().getFunction().getStops()).size());
-
- ExponentialStops<Stop.CompositeValue<Float, <%- propertyType(property) %>>, <%- propertyType(property) %>> stops =
- (ExponentialStops<Stop.CompositeValue<Float, <%- propertyType(property) %>>, <%- propertyType(property) %>>) layer.get<%- camelize(property.name) %>().getFunction().getStops();
- Stop<Stop.CompositeValue<Float, <%- propertyType(property) %>>, <%- propertyType(property) %>> stop = stops.iterator().next();
- assertEquals(0f, stop.in.zoom, 0.001);
- assertEquals(0.3f, stop.in.value, 0.001f);
- assertEquals(0.9f, stop.out, 0.001f);
- }
- });
- }
-<% } -%>
<% } -%>
<% } -%>
<% if (property.type == 'color') { -%>
@@ -443,18 +177,15 @@ public class <%- camelize(type) %>LayerTest extends BaseActivityTest {
validateTestSetup();
setupLayer();
Timber.i("<%- property.name %>");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(layer);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(layer);
- // Set and Get
- layer.setProperties(<%- camelizeWithLeadingLowercase(property.name) %>(Color.RED));
- assertEquals(layer.get<%- camelize(property.name) %>AsInt(), Color.RED);
- }
+ // Set and Get
+ layer.setProperties(<%- camelizeWithLeadingLowercase(property.name) %>(Color.RED));
+ assertEquals(layer.get<%- camelize(property.name) %>AsInt(), Color.RED);
});
}
<% } -%>
<% } -%>
-
-}
+<% } -%>
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs
index 2f22a8f3f0..c35168bb7a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/light.junit.ejs
@@ -9,15 +9,12 @@ import android.support.test.espresso.ViewAction;
import android.support.test.runner.AndroidJUnit4;
import android.view.View;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.light.Light;
-import com.mapbox.mapboxsdk.style.functions.Function;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer;
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
import com.mapbox.mapboxsdk.style.light.Position;
import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.mapboxsdk.testapp.action.MapboxMapAction;
import com.mapbox.mapboxsdk.testapp.activity.BaseActivityTest;
import com.mapbox.mapboxsdk.testapp.activity.style.FillExtrusionStyleTestActivity;
@@ -30,7 +27,7 @@ import org.junit.runner.RunWith;
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 com.mapbox.mapboxsdk.style.layers.Filter.eq;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
import static com.mapbox.mapboxsdk.style.layers.Property.ANCHOR_MAP;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionBase;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionColor;
@@ -53,15 +50,12 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("<%- property.name %>TransitionOptions");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- TransitionOptions options = new TransitionOptions(300, 100);
- light.set<%- camelize(property.name) %>Transition(options);
- assertEquals("Transition options should match", options, light.get<%- camelize(property.name) %>Transition());
- }
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ TransitionOptions options = new TransitionOptions(300, 100);
+ light.set<%- camelize(property.name) %>Transition(options);
+ assertEquals("Transition options should match", options, light.get<%- camelize(property.name) %>Transition());
});
}
<% } -%>
@@ -72,15 +66,12 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("<%- property.name %>");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- Position position = new Position(1, 2, 3);
- light.set<%- camelize(property.name) %>(position);
- assertEquals("Position should match", position, light.get<%- camelize(property.name) %>());
- }
+ invoke(mapboxMap,(uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ Position position = new Position(1, 2, 3);
+ light.set<%- camelize(property.name) %>(position);
+ assertEquals("Position should match", position, light.get<%- camelize(property.name) %>());
});
}
<% } else { -%>
@@ -90,18 +81,15 @@ public class LightTest extends BaseActivityTest {
validateTestSetup();
setupLight();
Timber.i("<%- property.name %>");
- invoke(mapboxMap, new MapboxMapAction.OnInvokeActionListener() {
- @Override
- public void onInvokeAction(UiController uiController, MapboxMap mapboxMap) {
- assertNotNull(light);
- // Set and Get
- light.set<%- camelize(property.name) %>(<%- defaultValueJava(property) %>);
+ invoke(mapboxMap, (uiController, mapboxMap) -> {
+ assertNotNull(light);
+ // Set and Get
+ light.set<%- camelize(property.name) %>(<%- defaultValueJava(property) %>);
<% if (property.name == 'color') { -%>
- assertEquals("<%- camelize(property.name) %> should match", <%- defaultValueJava(property) %>.replaceAll("\\s+", ""), light.get<%- camelize(property.name) %>());
+ assertEquals("<%- camelize(property.name) %> should match", <%- defaultValueJava(property) %>.replaceAll("\\s+", ""), light.get<%- camelize(property.name) %>());
<% } else { -%>
- assertEquals("<%- camelize(property.name) %> should match", <%- defaultValueJava(property) %>, light.get<%- camelize(property.name) %>());
+ assertEquals("<%- camelize(property.name) %> should match", <%- defaultValueJava(property) %>, light.get<%- camelize(property.name) %>());
<% } -%>
- }
});
}
<% } -%>
@@ -124,12 +112,12 @@ public class LightTest extends BaseActivityTest {
light = mapboxMap.getLight();
FillExtrusionLayer fillExtrusionLayer = new FillExtrusionLayer("3d-buildings", "composite");
fillExtrusionLayer.setSourceLayer("building");
- fillExtrusionLayer.setFilter(eq("extrude", "true"));
+ fillExtrusionLayer.setFilter(eq(Expression.get("extrude"), "true"));
fillExtrusionLayer.setMinZoom(15);
fillExtrusionLayer.setProperties(
fillExtrusionColor(Color.LTGRAY),
- fillExtrusionHeight(Function.property("height", new IdentityStops<Float>())),
- fillExtrusionBase(Function.property("min_height", new IdentityStops<Float>())),
+ fillExtrusionHeight(Expression.get("height")),
+ fillExtrusionBase(Expression.get("min_height")),
fillExtrusionOpacity(0.6f)
);
mapboxMap.addLayer(fillExtrusionLayer);
@@ -141,4 +129,4 @@ public class LightTest extends BaseActivityTest {
protected Class getActivityClass() {
return FillExtrusionStyleTestActivity.class;
}
-}
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
index 9d7e21024c..fb1d0ef8a2 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/AndroidManifest.xml
@@ -1,9 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="com.mapbox.mapboxsdk.testapp">
+ package="com.mapbox.mapboxsdk.testapp">
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
- <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<application
android:name=".MapboxApplication"
@@ -19,8 +18,9 @@
android:label="@string/app_name"
android:launchMode="singleTop">
<intent-filter>
- <action android:name="android.intent.action.MAIN"/>
- <category android:name="android.intent.category.LAUNCHER"/>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
@@ -29,10 +29,10 @@
android:label="@string/activity_info_window">
<meta-data
android:name="@string/category"
- android:value="@string/category_infowindow"/>
+ android:value="@string/category_infowindow" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.infowindow.InfoWindowAdapterActivity"
@@ -40,10 +40,10 @@
android:label="@string/activity_infowindow_adapter">
<meta-data
android:name="@string/category"
- android:value="@string/category_infowindow"/>
+ android:value="@string/category_infowindow" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.infowindow.DynamicInfoWindowAdapterActivity"
@@ -51,10 +51,10 @@
android:label="@string/activity_dynamic_infowindow_adapter">
<meta-data
android:name="@string/category"
- android:value="@string/category_infowindow"/>
+ android:value="@string/category_infowindow" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.annotation.BulkMarkerActivity"
@@ -63,10 +63,10 @@
android:label="@string/activity_add_bulk_markers">
<meta-data
android:name="@string/category"
- android:value="@string/category_annotation"/>
+ android:value="@string/category_annotation" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.annotation.AnimatedSymbolLayerActivity"
@@ -74,10 +74,10 @@
android:label="@string/activity_animated_symbollayer">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_annotation" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.annotation.DynamicMarkerChangeActivity"
@@ -85,10 +85,10 @@
android:label="@string/activity_dynamic_marker">
<meta-data
android:name="@string/category"
- android:value="@string/category_annotation"/>
+ android:value="@string/category_annotation" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.annotation.PressForMarkerActivity"
@@ -96,10 +96,10 @@
android:label="@string/activity_press_for_marker">
<meta-data
android:name="@string/category"
- android:value="@string/category_annotation"/>
+ android:value="@string/category_annotation" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.camera.CameraAnimationTypeActivity"
@@ -107,10 +107,10 @@
android:label="@string/activity_camera_animation_types">
<meta-data
android:name="@string/category"
- android:value="@string/category_camera"/>
+ android:value="@string/category_camera" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.camera.CameraAnimatorActivity"
@@ -118,10 +118,10 @@
android:label="@string/activity_camera_animator">
<meta-data
android:name="@string/category"
- android:value="@string/category_camera"/>
+ android:value="@string/category_camera" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.camera.CameraPositionActivity"
@@ -129,10 +129,10 @@
android:label="@string/activity_camera_position">
<meta-data
android:name="@string/category"
- android:value="@string/category_camera"/>
+ android:value="@string/category_camera" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.camera.LatLngBoundsActivity"
@@ -141,10 +141,10 @@
android:screenOrientation="portrait">
<meta-data
android:name="@string/category"
- android:value="@string/category_camera"/>
+ android:value="@string/category_camera" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.fragment.MapFragmentActivity"
@@ -152,10 +152,10 @@
android:label="@string/activity_map_fragment">
<meta-data
android:name="@string/category"
- android:value="@string/category_fragment"/>
+ android:value="@string/category_fragment" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.fragment.SupportMapFragmentActivity"
@@ -163,10 +163,10 @@
android:label="@string/activity_map_fragment_suport">
<meta-data
android:name="@string/category"
- android:value="@string/category_fragment"/>
+ android:value="@string/category_fragment" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.fragment.MultiMapActivity"
@@ -174,10 +174,10 @@
android:label="@string/activity_multimap">
<meta-data
android:name="@string/category"
- android:value="@string/category_fragment"/>
+ android:value="@string/category_fragment" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.camera.ManualZoomActivity"
@@ -185,10 +185,10 @@
android:label="@string/activity_camera_zoom">
<meta-data
android:name="@string/category"
- android:value="@string/category_camera"/>
+ android:value="@string/category_camera" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.camera.MaxMinZoomActivity"
@@ -196,10 +196,10 @@
android:label="@string/activity_minmax_zoom">
<meta-data
android:name="@string/category"
- android:value="@string/category_camera"/>
+ android:value="@string/category_camera" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.customlayer.CustomLayerActivity"
@@ -207,66 +207,10 @@
android:label="@string/activity_custom_layer">
<meta-data
android:name="@string/category"
- android:value="@string/category_custom_layer"/>
- <meta-data
- android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
- </activity>
- <activity
- android:name=".activity.userlocation.MyLocationTrackingModeActivity"
- android:description="@string/description_user_location_tracking"
- android:label="@string/activity_user_tracking_mode"
- android:theme="@style/NoActionBar">
- <meta-data
- android:name="@string/category"
- android:value="@string/category_userlocation"/>
- <meta-data
- android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
- </activity>
- <activity
- android:name=".activity.userlocation.MyLocationDrawableActivity"
- android:description="@string/description_user_location_customization"
- android:label="@string/activity_user_tracking_customization">
- <meta-data
- android:name="@string/category"
- android:value="@string/category_userlocation"/>
- <meta-data
- android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
- </activity>
- <activity
- android:name=".activity.userlocation.MyLocationTintActivity"
- android:description="@string/description_user_location_dot_color"
- android:label="@string/activity_user_dot_color">
- <meta-data
- android:name="@string/category"
- android:value="@string/category_userlocation"/>
- <meta-data
- android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
- </activity>
- <activity
- android:name=".activity.userlocation.MyLocationToggleActivity"
- android:description="@string/description_user_location_toggle"
- android:label="@string/activity_user_location_toggle">
- <meta-data
- android:name="@string/category"
- android:value="@string/category_userlocation"/>
+ android:value="@string/category_custom_layer" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
- </activity>
- <activity
- android:name=".activity.userlocation.CustomLocationEngineActivity"
- android:description="@string/description_custom_location_engine"
- android:label="@string/activity_custom_location_engine">
- <meta-data
- android:name="@string/category"
- android:value="@string/category_userlocation"/>
- <meta-data
- android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.annotation.PolygonActivity"
@@ -274,10 +218,10 @@
android:label="@string/activity_polygon">
<meta-data
android:name="@string/category"
- android:value="@string/category_annotation"/>
+ android:value="@string/category_annotation" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.annotation.PolylineActivity"
@@ -285,10 +229,10 @@
android:label="@string/activity_polyline">
<meta-data
android:name="@string/category"
- android:value="@string/category_annotation"/>
+ android:value="@string/category_annotation" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.camera.ScrollByActivity"
@@ -297,10 +241,10 @@
android:theme="@style/NoActionBar">
<meta-data
android:name="@string/category"
- android:value="@string/category_camera"/>
+ android:value="@string/category_camera" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.maplayout.MapPaddingActivity"
@@ -309,10 +253,10 @@
android:screenOrientation="portrait">
<meta-data
android:name="@string/category"
- android:value="@string/category_maplayout"/>
+ android:value="@string/category_maplayout" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.maplayout.DebugModeActivity"
@@ -321,7 +265,7 @@
android:label="@string/activity_debug_mode">
<meta-data
android:name="@string/category"
- android:value="@string/category_basic"/>
+ android:value="@string/category_basic" />
</activity>
<activity
android:name=".activity.offline.OfflineActivity"
@@ -329,10 +273,10 @@
android:label="@string/activity_offline">
<meta-data
android:name="@string/category"
- android:value="@string/category_offline"/>
+ android:value="@string/category_offline" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.offline.UpdateMetadataActivity"
@@ -340,10 +284,10 @@
android:label="@string/activity_update_metadata">
<meta-data
android:name="@string/category"
- android:value="@string/category_offline"/>
+ android:value="@string/category_offline" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.offline.DeleteRegionActivity"
@@ -351,10 +295,10 @@
android:label="@string/activity_offline_region_delete">
<meta-data
android:name="@string/category"
- android:value="@string/category_offline"/>
+ android:value="@string/category_offline" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.imagegenerator.SnapshotActivity"
@@ -362,10 +306,10 @@
android:label="@string/activity_snapshot">
<meta-data
android:name="@string/category"
- android:value="@string/category_imagegenerator"/>
+ android:value="@string/category_imagegenerator" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.snapshot.MapSnapshotterActivity"
@@ -373,10 +317,10 @@
android:label="@string/activity_map_snapshotter">
<meta-data
android:name="@string/category"
- android:value="@string/category_imagegenerator"/>
+ android:value="@string/category_imagegenerator" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.snapshot.MapSnapshotterReuseActivity"
@@ -384,10 +328,10 @@
android:label="@string/activity_map_snapshotter_reuse">
<meta-data
android:name="@string/category"
- android:value="@string/category_imagegenerator"/>
+ android:value="@string/category_imagegenerator" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.snapshot.MapSnapshotterMarkerActivity"
@@ -395,10 +339,10 @@
android:label="@string/activity_map_snapshotter_marker">
<meta-data
android:name="@string/category"
- android:value="@string/category_imagegenerator"/>
+ android:value="@string/category_imagegenerator" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.maplayout.DoubleMapActivity"
@@ -406,10 +350,10 @@
android:label="@string/activity_double_map">
<meta-data
android:name="@string/category"
- android:value="@string/category_maplayout"/>
+ android:value="@string/category_maplayout" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.annotation.MarkerViewActivity"
@@ -417,10 +361,10 @@
android:label="@string/activity_view_marker">
<meta-data
android:name="@string/category"
- android:value="@string/category_annotation"/>
+ android:value="@string/category_annotation" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.fragment.ViewPagerActivity"
@@ -428,10 +372,10 @@
android:label="@string/activity_viewpager">
<meta-data
android:name="@string/category"
- android:value="@string/category_fragment"/>
+ android:value="@string/category_fragment" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.maplayout.SimpleMapActivity"
@@ -439,10 +383,10 @@
android:label="@string/activity_simple_map">
<meta-data
android:name="@string/category"
- android:value="@string/category_basic"/>
+ android:value="@string/category_basic" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.maplayout.MapChangeActivity"
@@ -450,10 +394,10 @@
android:label="@string/activity_map_change">
<meta-data
android:name="@string/category"
- android:value="@string/category_maplayout"/>
+ android:value="@string/category_maplayout" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.maplayout.VisibilityChangeActivity"
@@ -461,10 +405,10 @@
android:label="@string/activity_map_visibility">
<meta-data
android:name="@string/category"
- android:value="@string/category_maplayout"/>
+ android:value="@string/category_maplayout" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.RuntimeStyleActivity"
@@ -472,10 +416,10 @@
android:label="@string/activity_runtime_style">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.DataDrivenStyleActivity"
@@ -483,10 +427,10 @@
android:label="@string/activity_data_driven_style">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.CircleLayerActivity"
@@ -494,10 +438,10 @@
android:label="@string/activity_circle_layer">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.FillExtrusionActivity"
@@ -505,10 +449,10 @@
android:label="@string/activity_fill_extrusion_layer">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.BuildingFillExtrusionActivity"
@@ -516,10 +460,10 @@
android:label="@string/activity_building_fill_extrusion_layer">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.SymbolLayerActivity"
@@ -527,10 +471,10 @@
android:label="@string/activity_symbol_layer">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.GeoJsonClusteringActivity"
@@ -538,10 +482,10 @@
android:label="@string/activity_geojson_clustering">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.RealTimeGeoJsonActivity"
@@ -549,10 +493,10 @@
android:label="@string/activity_geojson_realtime">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.StyleFileActivity"
@@ -560,10 +504,10 @@
android:label="@string/activity_style_file">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.CustomSpriteActivity"
@@ -571,10 +515,10 @@
android:label="@string/activity_add_sprite">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.imagegenerator.PrintActivity"
@@ -582,10 +526,10 @@
android:label="@string/activity_print">
<meta-data
android:name="@string/category"
- android:value="@string/category_imagegenerator"/>
+ android:value="@string/category_imagegenerator" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.AnimatedImageSourceActivity"
@@ -593,10 +537,10 @@
android:label="@string/activity_animated_image_source">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.GridSourceActivity"
@@ -604,10 +548,10 @@
android:label="@string/activity_grid_source">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<!-- Features -->
<activity
@@ -616,10 +560,10 @@
android:label="@string/activity_query_rendered_feature_properties">
<meta-data
android:name="@string/category"
- android:value="@string/category_features"/>
+ android:value="@string/category_features" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.feature.QueryRenderedFeaturesBoxCountActivity"
@@ -627,10 +571,10 @@
android:label="@string/activity_query_rendered_features_box_count">
<meta-data
android:name="@string/category"
- android:value="@string/category_features"/>
+ android:value="@string/category_features" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.feature.QueryRenderedFeaturesBoxSymbolCountActivity"
@@ -638,10 +582,10 @@
android:label="@string/activity_query_rendered_features_box_symbol_count">
<meta-data
android:name="@string/category"
- android:value="@string/category_features"/>
+ android:value="@string/category_features" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.feature.QueryRenderedFeaturesBoxHighlightActivity"
@@ -649,10 +593,10 @@
android:label="@string/activity_query_rendered_features_box_highlight">
<meta-data
android:name="@string/category"
- android:value="@string/category_features"/>
+ android:value="@string/category_features" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.feature.QuerySourceFeaturesActivity"
@@ -660,10 +604,10 @@
android:label="@string/activity_query_source_features">
<meta-data
android:name="@string/category"
- android:value="@string/category_features"/>
+ android:value="@string/category_features" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.SymbolGeneratorActivity"
@@ -671,10 +615,10 @@
android:label="@string/activity_symbol_generator">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.ZoomFunctionSymbolLayerActivity"
@@ -682,10 +626,10 @@
android:label="@string/activity_add_remove_markers">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.maplayout.MapInDialogActivity"
@@ -693,10 +637,10 @@
android:label="@string/activity_map_in_dialog">
<meta-data
android:name="@string/category"
- android:value="@string/category_maplayout"/>
+ android:value="@string/category_maplayout" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.annotation.MarkerViewsInRectangleActivity"
@@ -704,10 +648,10 @@
android:label="@string/activity_marker_view_rectangle">
<meta-data
android:name="@string/category"
- android:value="@string/category_annotation"/>
+ android:value="@string/category_annotation" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.maplayout.LatLngBoundsForCameraActivity"
@@ -715,10 +659,10 @@
android:label="@string/activity_restricted_bounds">
<meta-data
android:name="@string/category"
- android:value="@string/category_maplayout"/>
+ android:value="@string/category_maplayout" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<!-- Storage -->
@@ -728,10 +672,10 @@
android:label="@string/activity_url_transform">
<meta-data
android:name="@string/category"
- android:value="@string/category_storage"/>
+ android:value="@string/category_storage" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.maplayout.BottomSheetActivity"
@@ -739,7 +683,7 @@
android:label="@string/activity_bottom_sheet">
<meta-data
android:name="@string/category"
- android:value="@string/category_maplayout"/>
+ android:value="@string/category_maplayout" />
</activity>
<!-- TextureView -->
@@ -749,7 +693,7 @@
android:label="@string/activity_textureview_debug">
<meta-data
android:name="@string/category"
- android:value="@string/category_textureview"/>
+ android:value="@string/category_textureview" />
</activity>
<activity
android:name=".activity.textureview.TextureViewResizeActivity"
@@ -757,7 +701,18 @@
android:label="@string/activity_textureview_resize">
<meta-data
android:name="@string/category"
- android:value="@string/category_textureview"/>
+ android:value="@string/category_textureview" />
+ </activity>
+ <activity
+ android:name=".activity.textureview.TextureViewTransparentBackgroundActivity"
+ android:description="@string/description_textureview_transparent"
+ android:label="@string/activity_textureview_transparent">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_textureview" />
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.textureview.TextureViewAnimationActivity"
@@ -765,7 +720,7 @@
android:label="@string/activity_textureview_animate">
<meta-data
android:name="@string/category"
- android:value="@string/category_textureview"/>
+ android:value="@string/category_textureview" />
</activity>
<activity
android:name=".activity.maplayout.LocalGlyphActivity"
@@ -773,10 +728,10 @@
android:label="@string/activity_local_glyph">
<meta-data
android:name="@string/category"
- android:value="@string/category_maplayout"/>
+ android:value="@string/category_maplayout" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.HillshadeLayerActivity"
@@ -784,10 +739,10 @@
android:label="@string/activity_hillshade">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value=".activity.FeatureOverviewActivity" />
</activity>
<activity
android:name=".activity.style.HeatmapLayerActivity"
@@ -795,32 +750,43 @@
android:label="@string/activity_heatmaplayer">
<meta-data
android:name="@string/category"
- android:value="@string/category_style"/>
+ android:value="@string/category_style" />
+ <meta-data
+ android:name="android.support.PARENT_ACTIVITY"
+ android:value=".activity.FeatureOverviewActivity" />
+ </activity>
+ <activity
+ android:name=".activity.camera.GestureDetectorActivity"
+ android:label="@string/activity_gesture_detector"
+ android:description="@string/description_gesture_detector">
+ <meta-data
+ android:name="@string/category"
+ android:value="@string/category_camera" />
<meta-data
android:name="android.support.PARENT_ACTIVITY"
- android:value=".activity.FeatureOverviewActivity"/>
+ android:value="com.mapbox.mapboxsdk.testapp.activity.FeatureOverviewActivity" />
</activity>
<!-- For Instrumentation tests -->
<activity
android:name=".activity.style.RuntimeStyleTestActivity"
- android:screenOrientation="portrait"/>
+ android:screenOrientation="portrait" />
<activity
android:name=".activity.style.RuntimeStyleTimingTestActivity"
- android:screenOrientation="portrait"/>
+ android:screenOrientation="portrait" />
<activity
android:name=".activity.espresso.EspressoTestActivity"
- android:screenOrientation="portrait"/>
+ android:screenOrientation="portrait" />
<activity
android:name=".activity.style.FillExtrusionStyleTestActivity"
- android:screenOrientation="portrait"/>
+ android:screenOrientation="portrait" />
<!-- Configuration Settings -->
<meta-data
android:name="com.mapbox.TestEventsServer"
- android:value="api-events-staging.tilestream.net"/>
+ android:value="api-events-staging.tilestream.net" />
<meta-data
android:name="com.mapbox.TestEventsAccessToken"
- android:value="pk.eyJ1IjoiYmxzdGFnaW5nIiwiYSI6ImNpdDF3OHpoaTAwMDcyeXA5Y3Z0Nmk2dzEifQ.0IfB7v5Qbm2MGVYt8Kb8fg"/>
+ android:value="pk.eyJ1IjoiYmxzdGFnaW5nIiwiYSI6ImNpdDF3OHpoaTAwMDcyeXA5Y3Z0Nmk2dzEifQ.0IfB7v5Qbm2MGVYt8Kb8fg" />
<!-- Comment out this setting to switch to external storage (and disable internal) in your app -->
<!-- <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 fba33bb380..fa13959112 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
@@ -5,6 +5,7 @@ import android.os.StrictMode;
import android.text.TextUtils;
import com.mapbox.mapboxsdk.Mapbox;
+import com.mapbox.mapboxsdk.maps.Telemetry;
import com.mapbox.mapboxsdk.testapp.utils.TokenUtils;
import com.squareup.leakcanary.LeakCanary;
@@ -57,6 +58,8 @@ public class MapboxApplication extends Application {
}
Mapbox.getInstance(getApplicationContext(), mapboxAccessToken);
+
+ Telemetry.updateDebugLoggingEnabled(true);
}
private void initializeLogger() {
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 0ee1f78e0e..c8b15593ec 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
@@ -7,23 +7,17 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.AsyncTask;
-import android.os.Build;
import android.os.Bundle;
-import android.support.annotation.NonNull;
import android.support.annotation.StringRes;
-import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
-import android.text.TextUtils;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.adapter.FeatureAdapter;
import com.mapbox.mapboxsdk.testapp.adapter.FeatureSectionAdapter;
import com.mapbox.mapboxsdk.testapp.model.activity.Feature;
import com.mapbox.mapboxsdk.testapp.utils.ItemClickSupport;
-import com.mapbox.android.core.permissions.PermissionsListener;
-import com.mapbox.android.core.permissions.PermissionsManager;
import java.util.ArrayList;
import java.util.Collections;
@@ -39,23 +33,19 @@ import timber.log.Timber;
* It uses tags as category and description to order the different entries.
* </p>
*/
-public class FeatureOverviewActivity extends AppCompatActivity implements PermissionsListener {
+public class FeatureOverviewActivity extends AppCompatActivity {
private static final String KEY_STATE_FEATURES = "featureList";
- private PermissionsManager permissionsManager;
private RecyclerView recyclerView;
private FeatureSectionAdapter sectionAdapter;
private List<Feature> features;
- private int locationActivityInList;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_feature_overview);
- permissionsManager = new PermissionsManager(this);
-
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.addOnItemTouchListener(new RecyclerView.SimpleOnItemTouchListener());
@@ -65,11 +55,6 @@ public class FeatureOverviewActivity extends AppCompatActivity implements Permis
if (!sectionAdapter.isSectionHeaderPosition(position)) {
int itemPosition = sectionAdapter.getConvertedPosition(position);
Feature feature = features.get(itemPosition);
- if (feature.isRequiresLocationPermission()) {
- if (requestLocationPermission(itemPosition)) {
- return;
- }
- }
startFeature(feature);
}
});
@@ -118,45 +103,6 @@ public class FeatureOverviewActivity extends AppCompatActivity implements Permis
startActivity(intent);
}
- private boolean requestLocationPermission(final int positionInList) {
- if (isRuntimePermissionsRequired()) {
- locationActivityInList = positionInList;
- permissionsManager.requestLocationPermissions(this);
- return true;
- }
- return false;
- }
-
- @Override
- public void onExplanationNeeded(List<String> list) {
- Snackbar.make(
- findViewById(android.R.id.content),
- TextUtils.join("", list.toArray()),
- Snackbar.LENGTH_SHORT).show();
- }
-
- @Override
- public void onPermissionResult(boolean isPermissionGranted) {
- if (isPermissionGranted) {
- startFeature(features.get(locationActivityInList));
- } else {
- Snackbar.make(
- findViewById(android.R.id.content),
- "Can't open without accepting the location permission.",
- Snackbar.LENGTH_SHORT).show();
- }
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
- }
-
- private boolean isRuntimePermissionsRequired() {
- return android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
- }
-
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
@@ -178,8 +124,7 @@ public class FeatureOverviewActivity extends AppCompatActivity implements Permis
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));
+ features.add(new Feature(info.name, label, description, category));
}
}
@@ -213,24 +158,6 @@ public class FeatureOverviewActivity extends AppCompatActivity implements Permis
}
}
- private boolean requiresLocationPermission(String name, String category) {
- final Resources resources = getResources();
-
- List<String> requiresPermissionCategories = new ArrayList<String>() {
- {
- add(resources.getString(R.string.category_userlocation));
- }
- };
-
- List<String> requiresPermissionActivities = new ArrayList<String>() {
- {
- add(resources.getString(R.string.activity_double_map));
- }
- };
-
- return requiresPermissionCategories.contains(category) || requiresPermissionActivities.contains(name);
- }
-
@Override
protected void onPostExecute(List<Feature> features) {
super.onPostExecute(features);
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedSymbolLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedSymbolLayerActivity.java
deleted file mode 100644
index 97957720fc..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/annotation/AnimatedSymbolLayerActivity.java
+++ /dev/null
@@ -1,449 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.activity.annotation;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.TypeEvaluator;
-import android.animation.ValueAnimator;
-import android.graphics.drawable.BitmapDrawable;
-import android.os.Bundle;
-import android.support.v7.app.AppCompatActivity;
-import android.view.animation.AccelerateDecelerateInterpolator;
-import android.view.animation.LinearInterpolator;
-
-import com.google.gson.JsonObject;
-import com.mapbox.geojson.Feature;
-import com.mapbox.geojson.FeatureCollection;
-import com.mapbox.geojson.Point;
-import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.geometry.LatLngBounds;
-import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.stops.Stops;
-import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
-import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.turf.TurfMeasurement;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Random;
-
-import static com.mapbox.mapboxsdk.style.functions.Function.property;
-import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
-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.iconRotate;
-
-/**
- * Test activity showcasing animating MarkerViews.
- */
-public class AnimatedSymbolLayerActivity extends AppCompatActivity {
-
- private static final String PASSENGER = "passenger";
- private static final String PASSENGER_LAYER = "passenger-layer";
- private static final String PASSENGER_SOURCE = "passenger-source";
- private static final String TAXI = "taxi";
- private static final String TAXI_LAYER = "taxi-layer";
- private static final String TAXI_SOURCE = "taxi-source";
- private static final String RANDOM_CAR_LAYER = "random-car-layer";
- private static final String RANDOM_CAR_SOURCE = "random-car-source";
- private static final String RANDOM_CAR_IMAGE_ID = "random-car";
- private static final String PROPERTY_BEARING = "bearing";
- private static final String WATERWAY_LAYER_ID = "waterway-label";
- private static final int DURATION_RANDOM_MAX = 1500;
- private static final int DURATION_BASE = 3000;
-
- private final Random random = new Random();
-
- private MapView mapView;
- private MapboxMap mapboxMap;
-
- private List<Car> randomCars = new ArrayList<>();
- private GeoJsonSource randomCarSource;
- private Car taxi;
- private GeoJsonSource taxiSource;
- private LatLng passenger;
-
- private List<Animator> animators = new ArrayList<>();
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_animated_marker);
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(mapboxMap -> {
- AnimatedSymbolLayerActivity.this.mapboxMap = mapboxMap;
- setupCars();
- animateRandomRoutes();
- animateTaxi();
- });
- }
-
- private void setupCars() {
- addRandomCars();
- addPassenger();
- addMainCar();
- }
-
- private void animateRandomRoutes() {
- final Car longestDrive = getLongestDrive();
- final Random random = new Random();
- for (final Car car : randomCars) {
- final boolean isLongestDrive = longestDrive.equals(car);
- ValueAnimator valueAnimator = ValueAnimator.ofObject(new LatLngEvaluator(), car.current, car.next);
- valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-
- private LatLng latLng;
-
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- latLng = (LatLng) animation.getAnimatedValue();
- car.current = latLng;
- if (isLongestDrive) {
- updateRandomCarSource();
- }
- }
- });
-
- if (isLongestDrive) {
- valueAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- updateRandomDestinations();
- animateRandomRoutes();
- }
- });
- }
-
- valueAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
- car.feature.properties().addProperty("bearing", Car.getBearing(car.current, car.next));
- }
- });
-
- int offset = random.nextInt(2) == 0 ? 0 : random.nextInt(1000) + 250;
- valueAnimator.setStartDelay(offset);
- valueAnimator.setDuration(car.duration - offset);
- valueAnimator.setInterpolator(new LinearInterpolator());
- valueAnimator.start();
-
- animators.add(valueAnimator);
- }
- }
-
- private void animateTaxi() {
- ValueAnimator valueAnimator = ValueAnimator.ofObject(new LatLngEvaluator(), taxi.current, taxi.next);
- valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-
- private LatLng latLng;
-
- @Override
- public void onAnimationUpdate(ValueAnimator animation) {
- latLng = (LatLng) animation.getAnimatedValue();
- taxi.current = latLng;
- updateTaxiSource();
- }
- });
-
- valueAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationEnd(Animator animation) {
- super.onAnimationEnd(animation);
- updatePassenger();
- animateTaxi();
- }
- });
-
- valueAnimator.addListener(new AnimatorListenerAdapter() {
- @Override
- public void onAnimationStart(Animator animation) {
- super.onAnimationStart(animation);
- taxi.feature.properties().addProperty("bearing", Car.getBearing(taxi.current, taxi.next));
- }
- });
-
- valueAnimator.setDuration((long) (7 * taxi.current.distanceTo(taxi.next)));
- valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
- valueAnimator.start();
-
- animators.add(valueAnimator);
- }
-
- private void updatePassenger() {
- passenger = getLatLngInBounds();
- updatePassengerSource();
- taxi.setNext(passenger);
- }
-
- private void updatePassengerSource() {
- GeoJsonSource source = mapboxMap.getSourceAs(PASSENGER_SOURCE);
- FeatureCollection featureCollection = FeatureCollection.fromFeatures(new Feature[] {
- Feature.fromGeometry(
- Point.fromLngLat(
- passenger.getLongitude(),
- passenger.getLatitude()
- )
- )
- });
- source.setGeoJson(featureCollection);
- }
-
- private void updateTaxiSource() {
- taxi.updateFeature();
- taxiSource.setGeoJson(taxi.feature);
- }
-
- private void updateRandomDestinations() {
- for (Car randomCar : randomCars) {
- randomCar.setNext(getLatLngInBounds());
- }
- }
-
- private Car getLongestDrive() {
- Car longestDrive = null;
- for (Car randomCar : randomCars) {
- if (longestDrive == null) {
- longestDrive = randomCar;
- } else if (longestDrive.duration < randomCar.duration) {
- longestDrive = randomCar;
- }
- }
- return longestDrive;
- }
-
- private void updateRandomCarSource() {
- for (Car randomCarsRoute : randomCars) {
- randomCarsRoute.updateFeature();
- }
- randomCarSource.setGeoJson(featuresFromRoutes());
- }
-
- private FeatureCollection featuresFromRoutes() {
- List<Feature> features = new ArrayList<>();
- for (Car randomCarsRoute : randomCars) {
- features.add(randomCarsRoute.feature);
- }
- return FeatureCollection.fromFeatures(features);
- }
-
- private long getDuration() {
- return random.nextInt(DURATION_RANDOM_MAX) + DURATION_BASE;
- }
-
- private void addRandomCars() {
- LatLng latLng;
- LatLng next;
- for (int i = 0; i < 10; i++) {
- latLng = getLatLngInBounds();
- next = getLatLngInBounds();
-
- JsonObject properties = new JsonObject();
- properties.addProperty(PROPERTY_BEARING, Car.getBearing(latLng, next));
-
- Feature feature = Feature.fromGeometry(
- Point.fromLngLat(
- latLng.getLongitude(),
- latLng.getLatitude()
- ), properties);
-
- randomCars.add(
- new Car(feature, next, getDuration())
- );
- }
-
- randomCarSource = new GeoJsonSource(RANDOM_CAR_SOURCE, featuresFromRoutes());
- mapboxMap.addSource(randomCarSource);
- mapboxMap.addImage(RANDOM_CAR_IMAGE_ID,
- ((BitmapDrawable) getResources().getDrawable(R.drawable.ic_car_top)).getBitmap());
-
- SymbolLayer symbolLayer = new SymbolLayer(RANDOM_CAR_LAYER, RANDOM_CAR_SOURCE);
- symbolLayer.withProperties(
- iconImage(RANDOM_CAR_IMAGE_ID),
- iconAllowOverlap(true),
- iconRotate(
- property(
- PROPERTY_BEARING,
- Stops.<Float>identity()
- )
- ),
- iconIgnorePlacement(true)
- );
-
- mapboxMap.addLayerBelow(symbolLayer, WATERWAY_LAYER_ID);
- }
-
- private void addPassenger() {
- passenger = getLatLngInBounds();
- FeatureCollection featureCollection = FeatureCollection.fromFeatures(new Feature[] {
- Feature.fromGeometry(
- Point.fromLngLat(
- passenger.getLongitude(),
- passenger.getLatitude()
- )
- )
- });
-
- mapboxMap.addImage(PASSENGER,
- ((BitmapDrawable) getResources().getDrawable(R.drawable.icon_burned)).getBitmap());
-
- GeoJsonSource geoJsonSource = new GeoJsonSource(PASSENGER_SOURCE, featureCollection);
- mapboxMap.addSource(geoJsonSource);
-
- SymbolLayer symbolLayer = new SymbolLayer(PASSENGER_LAYER, PASSENGER_SOURCE);
- symbolLayer.withProperties(
- iconImage(PASSENGER),
- iconIgnorePlacement(true),
- iconAllowOverlap(true)
- );
- mapboxMap.addLayerBelow(symbolLayer, RANDOM_CAR_LAYER);
- }
-
- private void addMainCar() {
- LatLng latLng = getLatLngInBounds();
- JsonObject properties = new JsonObject();
- properties.addProperty(PROPERTY_BEARING, Car.getBearing(latLng, passenger));
- Feature feature = Feature.fromGeometry(
- Point.fromLngLat(
- latLng.getLongitude(),
- latLng.getLatitude()), properties);
- FeatureCollection featureCollection = FeatureCollection.fromFeatures(new Feature[] {feature});
-
- taxi = new Car(feature, passenger, getDuration());
- mapboxMap.addImage(TAXI,
- ((BitmapDrawable) getResources().getDrawable(R.drawable.ic_taxi_top)).getBitmap());
- taxiSource = new GeoJsonSource(TAXI_SOURCE, featureCollection);
- mapboxMap.addSource(taxiSource);
-
- SymbolLayer symbolLayer = new SymbolLayer(TAXI_LAYER, TAXI_SOURCE);
- symbolLayer.withProperties(
- iconImage(TAXI),
- iconRotate(
- property(
- PROPERTY_BEARING,
- Stops.<Float>identity()
- )
- ),
- iconAllowOverlap(true),
- iconIgnorePlacement(true)
-
- );
- mapboxMap.addLayer(symbolLayer);
- }
-
- 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
- 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();
-
- for (Animator animator : animators) {
- if (animator != null) {
- animator.removeAllListeners();
- animator.cancel();
- }
- }
-
- 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 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 static class Car {
- private Feature feature;
- private LatLng next;
- private LatLng current;
- private long duration;
-
- Car(Feature feature, LatLng next, long duration) {
- this.feature = feature;
- Point point = ((Point) feature.geometry());
- this.current = new LatLng(point.latitude(), point.longitude());
- this.duration = duration;
- this.next = next;
- }
-
- void setNext(LatLng next) {
- this.next = next;
- }
-
- void updateFeature() {
- feature = Feature.fromGeometry(Point.fromLngLat(
- current.getLongitude(),
- current.getLatitude())
- );
- feature.properties().addProperty("bearing", getBearing(current, next));
- }
-
- private static float getBearing(LatLng from, LatLng to) {
- return (float) TurfMeasurement.bearing(
- Point.fromLngLat(from.getLongitude(), from.getLatitude()),
- Point.fromLngLat(to.getLongitude(), to.getLatitude())
- );
- }
- }
-} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java
index 176d713a4b..5983fb367a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/CameraAnimatorActivity.java
@@ -115,7 +115,9 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
ValueAnimator latLngAnimator = ValueAnimator.ofObject(new LatLngEvaluator(), currentPosition, targetPosition);
latLngAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR));
latLngAnimator.setInterpolator(new FastOutSlowInInterpolator());
- latLngAnimator.addUpdateListener(animation -> mapboxMap.setLatLng((LatLng) animation.getAnimatedValue()));
+ latLngAnimator.addUpdateListener(animation -> mapboxMap.moveCamera(
+ CameraUpdateFactory.newLatLng((LatLng) animation.getAnimatedValue()))
+ );
return latLngAnimator;
}
@@ -124,7 +126,9 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
zoomAnimator.setDuration((long) (2200 * ANIMATION_DELAY_FACTOR));
zoomAnimator.setStartDelay((long) (600 * ANIMATION_DELAY_FACTOR));
zoomAnimator.setInterpolator(new AnticipateOvershootInterpolator());
- zoomAnimator.addUpdateListener(animation -> mapboxMap.setZoom((Float) animation.getAnimatedValue()));
+ zoomAnimator.addUpdateListener(animation -> mapboxMap.moveCamera(
+ CameraUpdateFactory.zoomTo((Float) animation.getAnimatedValue()))
+ );
return zoomAnimator;
}
@@ -133,7 +137,9 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
bearingAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR));
bearingAnimator.setStartDelay((long) (1000 * ANIMATION_DELAY_FACTOR));
bearingAnimator.setInterpolator(new FastOutLinearInInterpolator());
- bearingAnimator.addUpdateListener(animation -> mapboxMap.setBearing((Float) animation.getAnimatedValue()));
+ bearingAnimator.addUpdateListener(animation -> mapboxMap.moveCamera(
+ CameraUpdateFactory.bearingTo((Float) animation.getAnimatedValue()))
+ );
return bearingAnimator;
}
@@ -141,7 +147,9 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
ValueAnimator tiltAnimator = ValueAnimator.ofFloat((float) currentTilt, (float) targetTilt);
tiltAnimator.setDuration((long) (1000 * ANIMATION_DELAY_FACTOR));
tiltAnimator.setStartDelay((long) (1500 * ANIMATION_DELAY_FACTOR));
- tiltAnimator.addUpdateListener(animation -> mapboxMap.setTilt((Float) animation.getAnimatedValue()));
+ tiltAnimator.addUpdateListener(animation -> mapboxMap.moveCamera(
+ CameraUpdateFactory.tiltTo((Float) animation.getAnimatedValue()))
+ );
return tiltAnimator;
}
@@ -195,7 +203,9 @@ public class CameraAnimatorActivity extends AppCompatActivity implements OnMapRe
ValueAnimator zoomAnimator = ValueAnimator.ofFloat(11.0f, 16.0f);
zoomAnimator.setDuration((long) (duration * ANIMATION_DELAY_FACTOR));
zoomAnimator.setInterpolator(interpolator);
- zoomAnimator.addUpdateListener(animation -> mapboxMap.setZoom((Float) animation.getAnimatedValue()));
+ zoomAnimator.addUpdateListener(animation -> mapboxMap.moveCamera(
+ CameraUpdateFactory.zoomTo((Float) animation.getAnimatedValue()))
+ );
return zoomAnimator;
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/GestureDetectorActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/GestureDetectorActivity.java
new file mode 100644
index 0000000000..c1698e20ab
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/camera/GestureDetectorActivity.java
@@ -0,0 +1,422 @@
+package com.mapbox.mapboxsdk.testapp.activity.camera;
+
+import android.graphics.Typeface;
+import android.os.Bundle;
+import android.os.Handler;
+import android.support.annotation.ColorInt;
+import android.support.annotation.IntDef;
+import android.support.annotation.Nullable;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.AppCompatActivity;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.mapbox.android.gestures.AndroidGesturesManager;
+import com.mapbox.android.gestures.MoveGestureDetector;
+import com.mapbox.android.gestures.RotateGestureDetector;
+import com.mapbox.android.gestures.ShoveGestureDetector;
+import com.mapbox.android.gestures.StandardScaleGestureDetector;
+import com.mapbox.mapboxsdk.annotations.Marker;
+import com.mapbox.mapboxsdk.annotations.MarkerOptions;
+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 com.mapbox.mapboxsdk.testapp.utils.FontCache;
+import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
+
+import java.lang.annotation.Retention;
+import java.util.ArrayList;
+import java.util.List;
+
+import static java.lang.annotation.RetentionPolicy.SOURCE;
+
+/**
+ * Test activity showcasing APIs around gestures implementation.
+ */
+public class GestureDetectorActivity extends AppCompatActivity {
+
+ private static final int MAX_NUMBER_OF_ALERTS = 30;
+
+ private MapView mapView;
+ private MapboxMap mapboxMap;
+ private RecyclerView recyclerView;
+ private GestureAlertsAdapter gestureAlertsAdapter;
+
+ private AndroidGesturesManager gesturesManager;
+
+ @Nullable
+ private Marker marker;
+ @Nullable
+ private LatLng focalPointLatLng;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_gesture_detector);
+
+ mapView = (MapView) findViewById(R.id.mapView);
+ mapView.onCreate(savedInstanceState);
+ mapView.getMapAsync(new OnMapReadyCallback() {
+ @Override
+ public void onMapReady(MapboxMap mapboxMap) {
+ GestureDetectorActivity.this.mapboxMap = mapboxMap;
+ initializeMap();
+ }
+ });
+
+ recyclerView = (RecyclerView) findViewById(R.id.alerts_recycler);
+ recyclerView.setLayoutManager(new LinearLayoutManager(this));
+
+ gestureAlertsAdapter = new GestureAlertsAdapter();
+ recyclerView.setAdapter(gestureAlertsAdapter);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ mapView.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ gestureAlertsAdapter.cancelUpdates();
+ mapView.onPause();
+ }
+
+ @Override
+ protected void onStart() {
+ super.onStart();
+ mapView.onStart();
+ }
+
+ @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);
+ }
+
+ private void initializeMap() {
+ gesturesManager = mapboxMap.getGesturesManager();
+
+ RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) recyclerView.getLayoutParams();
+ layoutParams.height = (int) (mapView.getHeight() / 1.75);
+ layoutParams.width = (mapView.getWidth() / 3);
+ recyclerView.setLayoutParams(layoutParams);
+
+ attachListeners();
+ }
+
+ public void attachListeners() {
+ mapboxMap.addOnMoveListener(new MapboxMap.OnMoveListener() {
+ @Override
+ public void onMoveBegin(MoveGestureDetector detector) {
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_START, "MOVE START"));
+ }
+
+ @Override
+ public void onMove(MoveGestureDetector detector) {
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_PROGRESS, "MOVE PROGRESS"));
+ }
+
+ @Override
+ public void onMoveEnd(MoveGestureDetector detector) {
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_END, "MOVE END"));
+ }
+ });
+
+ mapboxMap.addOnRotateListener(new MapboxMap.OnRotateListener() {
+ @Override
+ public void onRotateBegin(RotateGestureDetector detector) {
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_START, "ROTATE START"));
+ }
+
+ @Override
+ public void onRotate(RotateGestureDetector detector) {
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_PROGRESS, "ROTATE PROGRESS"));
+ recalculateFocalPoint();
+ }
+
+ @Override
+ public void onRotateEnd(RotateGestureDetector detector) {
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_END, "ROTATE END"));
+ }
+ });
+
+ mapboxMap.addOnScaleListener(new MapboxMap.OnScaleListener() {
+ @Override
+ public void onScaleBegin(StandardScaleGestureDetector detector) {
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_START, "SCALE START"));
+ if (focalPointLatLng != null) {
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_OTHER, "INCREASING MOVE THRESHOLD"));
+ gesturesManager.getMoveGestureDetector().setMoveThreshold(
+ ResourceUtils.convertDpToPx(GestureDetectorActivity.this, 175));
+
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_OTHER, "MANUALLY INTERRUPTING MOVE"));
+ gesturesManager.getMoveGestureDetector().interrupt();
+ }
+ recalculateFocalPoint();
+ }
+
+ @Override
+ public void onScale(StandardScaleGestureDetector detector) {
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_PROGRESS, "SCALE PROGRESS"));
+ }
+
+ @Override
+ public void onScaleEnd(StandardScaleGestureDetector detector) {
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_END, "SCALE END"));
+
+ if (focalPointLatLng != null) {
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_OTHER, "REVERTING MOVE THRESHOLD"));
+ gesturesManager.getMoveGestureDetector().setMoveThreshold(0f);
+ }
+ }
+ });
+
+ mapboxMap.addOnShoveListener(new MapboxMap.OnShoveListener() {
+ @Override
+ public void onShoveBegin(ShoveGestureDetector detector) {
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_START, "SHOVE START"));
+ }
+
+ @Override
+ public void onShove(ShoveGestureDetector detector) {
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_PROGRESS, "SHOVE PROGRESS"));
+ }
+
+ @Override
+ public void onShoveEnd(ShoveGestureDetector detector) {
+ gestureAlertsAdapter.addAlert(new GestureAlert(GestureAlert.TYPE_END, "SHOVE END"));
+ }
+ });
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.menu_gestures, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ resetModes();
+ switch (item.getItemId()) {
+ case R.id.menu_gesture_none:
+ return true;
+ case R.id.menu_gesture_focus_point:
+ focalPointLatLng = new LatLng(51.50325, -0.12968);
+ marker = mapboxMap.addMarker(new MarkerOptions().position(focalPointLatLng));
+ mapboxMap.easeCamera(CameraUpdateFactory.newLatLngZoom(focalPointLatLng, 16));
+ mapboxMap.getUiSettings().setFocalPoint(mapboxMap.getProjection().toScreenLocation(focalPointLatLng));
+ return true;
+ case R.id.menu_gesture_animation:
+ mapboxMap.getUiSettings().setAllVelocityAnimationsEnabled(false);
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void resetModes() {
+ focalPointLatLng = null;
+ mapboxMap.getUiSettings().setFocalPoint(null);
+ gesturesManager.getMoveGestureDetector().setMoveThreshold(0f);
+ mapboxMap.getUiSettings().setAllVelocityAnimationsEnabled(true);
+
+ if (marker != null) {
+ mapboxMap.removeMarker(marker);
+ marker = null;
+ }
+ }
+
+ private void recalculateFocalPoint() {
+ if (focalPointLatLng != null) {
+ mapboxMap.getUiSettings().setFocalPoint(
+ mapboxMap.getProjection().toScreenLocation(focalPointLatLng)
+ );
+ }
+ }
+
+ private static class GestureAlertsAdapter extends RecyclerView.Adapter<GestureAlertsAdapter.ViewHolder> {
+
+ private boolean isUpdating;
+ private final Handler updateHandler = new Handler();
+ private final List<GestureAlert> alerts = new ArrayList<>();
+
+ public static class ViewHolder extends RecyclerView.ViewHolder {
+
+ TextView alertMessageTv;
+
+ @ColorInt
+ public int textColor;
+
+ ViewHolder(View view) {
+ super(view);
+ Typeface typeface = FontCache.get("Roboto-Regular.ttf", view.getContext());
+ alertMessageTv = (TextView) view.findViewById(R.id.alert_message);
+ alertMessageTv.setTypeface(typeface);
+ }
+ }
+
+
+ @Override
+ public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_gesture_alert, parent, false);
+ return new ViewHolder(view);
+ }
+
+ @Override
+ public void onBindViewHolder(ViewHolder holder, int position) {
+ GestureAlert alert = alerts.get(position);
+ holder.alertMessageTv.setText(alert.getMessage());
+ holder.alertMessageTv.setTextColor(
+ ContextCompat.getColor(holder.alertMessageTv.getContext(), alert.getColor()));
+ }
+
+ @Override
+ public int getItemCount() {
+ return alerts.size();
+ }
+
+ void addAlert(GestureAlert alert) {
+ for (GestureAlert gestureAlert : alerts) {
+ if (gestureAlert.getAlertType() != GestureAlert.TYPE_PROGRESS) {
+ break;
+ }
+
+ if (alert.getAlertType() == GestureAlert.TYPE_PROGRESS && gestureAlert.equals(alert)) {
+ return;
+ }
+ }
+
+ if (getItemCount() >= MAX_NUMBER_OF_ALERTS) {
+ alerts.remove(getItemCount() - 1);
+ }
+
+ alerts.add(0, alert);
+ if (!isUpdating) {
+ isUpdating = true;
+ updateHandler.postDelayed(updateRunnable, 250);
+ }
+ }
+
+ private Runnable updateRunnable = new Runnable() {
+ @Override
+ public void run() {
+ notifyDataSetChanged();
+ isUpdating = false;
+ }
+ };
+
+ void cancelUpdates() {
+ updateHandler.removeCallbacksAndMessages(null);
+ }
+ }
+
+ private static class GestureAlert {
+ @Retention(SOURCE)
+ @IntDef( {TYPE_NONE, TYPE_START, TYPE_PROGRESS, TYPE_END, TYPE_OTHER})
+ @interface Type {
+ }
+
+ static final int TYPE_NONE = 0;
+ static final int TYPE_START = 1;
+ static final int TYPE_END = 2;
+ static final int TYPE_PROGRESS = 3;
+ static final int TYPE_OTHER = 4;
+
+ @Type
+ private int alertType;
+
+ private String message;
+
+ @ColorInt
+ private int color;
+
+ GestureAlert(@Type int alertType, String message) {
+ this.alertType = alertType;
+ this.message = message;
+
+ switch (alertType) {
+ case TYPE_NONE:
+ color = android.R.color.black;
+ break;
+ case TYPE_END:
+ color = android.R.color.holo_red_dark;
+ break;
+ case TYPE_OTHER:
+ color = android.R.color.holo_purple;
+ break;
+ case TYPE_PROGRESS:
+ color = android.R.color.holo_orange_dark;
+ break;
+ case TYPE_START:
+ color = android.R.color.holo_green_dark;
+ break;
+ }
+ }
+
+ int getAlertType() {
+ return alertType;
+ }
+
+ String getMessage() {
+ return message;
+ }
+
+ int getColor() {
+ return color;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ GestureAlert that = (GestureAlert) o;
+
+ if (alertType != that.alertType) {
+ return false;
+ }
+ return message != null ? message.equals(that.message) : that.message == null;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = alertType;
+ result = 31 * result + (message != null ? message.hashCode() : 0);
+ return result;
+ }
+ }
+}
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 4cad7593ef..7685dee840 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
@@ -58,11 +58,7 @@ public class CustomLayerActivity extends AppCompatActivity {
fab.setImageResource(R.drawable.ic_layers);
} else {
customLayer = new CustomLayer("custom",
- ExampleCustomLayer.createContext(),
- ExampleCustomLayer.InitializeFunction,
- ExampleCustomLayer.RenderFunction,
- ExampleCustomLayer.ContextLostFunction, // Optional
- ExampleCustomLayer.DeinitializeFunction);
+ ExampleCustomLayer.createContext());
mapboxMap.addLayerBelow(customLayer, "building");
fab.setImageResource(R.drawable.ic_layers_clear);
}
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 df608360ad..7953824c36 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
@@ -11,16 +11,19 @@ import com.mapbox.geojson.Feature;
import com.mapbox.geojson.FeatureCollection;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
-import com.mapbox.mapboxsdk.style.layers.Filter;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.testapp.R;
-
import java.util.List;
import timber.log.Timber;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.lt;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.toNumber;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillColor;
/**
@@ -58,7 +61,9 @@ public class QueryRenderedFeaturesBoxHighlightActivity extends AppCompatActivity
int left = selectionBox.getLeft() - mapView.getLeft();
RectF box = new RectF(left, top, left + selectionBox.getWidth(), top + selectionBox.getHeight());
Timber.i("Querying box %s for buildings", box);
- List<Feature> features = mapboxMap.queryRenderedFeatures(box, Filter.lt("height", 10), "building");
+
+ Expression filter = lt(toNumber(get("height")), literal(10));
+ List<Feature> features = mapboxMap.queryRenderedFeatures(box, filter, "building");
// Show count
Toast.makeText(
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QuerySourceFeaturesActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QuerySourceFeaturesActivity.java
index 14de81ab30..79069a26f7 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QuerySourceFeaturesActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/feature/QuerySourceFeaturesActivity.java
@@ -11,13 +11,16 @@ import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
-import com.mapbox.mapboxsdk.style.layers.Filter;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.testapp.R;
-
import java.util.List;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.neq;
+
/**
* Test activity showcasing using the query source features API to query feature counts
*/
@@ -31,8 +34,6 @@ public class QuerySourceFeaturesActivity extends AppCompatActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_query_source_features);
- final float density = getResources().getDisplayMetrics().density;
-
// Initialize map as normal
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
@@ -47,12 +48,12 @@ public class QuerySourceFeaturesActivity extends AppCompatActivity {
}));
mapboxMap.addSource(source);
- mapboxMap.addLayer(new CircleLayer("test-layer", source.getId()).withFilter(Filter.neq("key1", "value1")));
+ mapboxMap.addLayer(new CircleLayer("test-layer", source.getId()).withFilter(neq(get("key1"), literal("value1"))));
// Add a click listener
mapboxMap.setOnMapClickListener(point -> {
// Query
- List<Feature> features = source.querySourceFeatures(Filter.eq("key1", "value1"));
+ List<Feature> features = source.querySourceFeatures(eq(get("key1"), literal("value1")));
Toast.makeText(QuerySourceFeaturesActivity.this, String.format("Found %s features",
features.size()), Toast.LENGTH_SHORT).show();
});
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 62d3ad34df..1ec9d48a51 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
@@ -1,5 +1,6 @@
package com.mapbox.mapboxsdk.testapp.activity.imagegenerator;
+import android.graphics.Bitmap;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.content.ContextCompat;
@@ -16,6 +17,8 @@ import com.mapbox.mapboxsdk.testapp.R;
import java.util.Locale;
+import timber.log.Timber;
+
/**
* Test activity showcasing the Snapshot API to create and display a bitmap of the current shown Map.
*/
@@ -75,6 +78,12 @@ public class SnapshotActivity extends AppCompatActivity implements OnMapReadyCal
@Override
protected void onPause() {
super.onPause();
+ mapboxMap.snapshot(new MapboxMap.SnapshotReadyCallback() {
+ @Override
+ public void onSnapshotReady(Bitmap snapshot) {
+ Timber.e("Regression test for https://github.com/mapbox/mapbox-gl-native/pull/11358");
+ }
+ });
mapView.onPause();
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/BottomSheetActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/BottomSheetActivity.java
index 3b58843e13..a165d9ab9d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/BottomSheetActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/maplayout/BottomSheetActivity.java
@@ -1,7 +1,6 @@
package com.mapbox.mapboxsdk.testapp.activity.maplayout;
import android.content.Context;
-import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
@@ -151,10 +150,7 @@ public class BottomSheetActivity extends AppCompatActivity {
@Override
public void onMapReady(MapboxMap mapboxMap) {
- Location location = mapboxMap.getMyLocation();
- if (location != null) {
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), 15));
- }
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(37.760545, -122.436055), 15));
}
@Override
@@ -207,7 +203,6 @@ public class BottomSheetActivity extends AppCompatActivity {
public static BottomSheetFragment newInstance() {
BottomSheetFragment mapFragment = new BottomSheetFragment();
MapboxMapOptions mapboxMapOptions = new MapboxMapOptions();
- mapboxMapOptions.locationEnabled(true);
mapboxMapOptions.renderSurfaceOnTop(true);
mapboxMapOptions.styleUrl(Style.LIGHT);
mapFragment.setArguments(MapFragmentUtils.createFragmentArgs(mapboxMapOptions));
@@ -230,10 +225,7 @@ public class BottomSheetActivity extends AppCompatActivity {
@Override
public void onMapReady(MapboxMap mapboxMap) {
- Location location = mapboxMap.getMyLocation();
- if (location != null) {
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), 15));
- }
+ mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(37.760545, -122.436055), 15));
}
@Override
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 75b2378ef7..b4dde8d2cd 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
@@ -11,11 +11,9 @@ import android.view.View;
import android.view.ViewGroup;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.constants.MyLocationTracking;
import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.TrackingSettings;
import com.mapbox.mapboxsdk.maps.UiSettings;
import com.mapbox.mapboxsdk.testapp.R;
@@ -50,14 +48,6 @@ public class DoubleMapActivity extends AppCompatActivity {
mapboxMap = map;
mapboxMap.setStyleUrl(Style.DARK);
mapboxMap.moveCamera(CameraUpdateFactory.zoomTo(18));
- try {
- mapboxMap.setMyLocationEnabled(true);
- TrackingSettings settings = mapboxMap.getTrackingSettings();
- settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
- } catch (SecurityException securityException) {
- // permission is handled in MainActivity
- finish();
- }
}
/**
@@ -106,15 +96,6 @@ public class DoubleMapActivity extends AppCompatActivity {
uiSettings.setAttributionEnabled(false);
uiSettings.setLogoEnabled(false);
- try {
- mapboxMap.setMyLocationEnabled(true);
- TrackingSettings settings = mapboxMap.getTrackingSettings();
- settings.setMyLocationTrackingMode(MyLocationTracking.TRACKING_FOLLOW);
- } catch (SecurityException securityException) {
- // permission is handled in MainActivity
- getActivity().finish();
- }
-
mapboxMap.setOnMapClickListener(point -> {
// test if we can open 2 activities after each other
startActivity(new Intent(mapViewMini.getContext(), DoubleMapActivity.class));
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 9a6079b157..d547866239 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
@@ -8,18 +8,13 @@ import android.view.MenuItem;
import com.mapbox.mapboxsdk.annotations.MarkerOptions;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.constants.MyLocationTracking;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.TrackingSettings;
import com.mapbox.mapboxsdk.testapp.R;
/**
* Test activity showcasing using the map padding API.
- * <p>
- * This activity tests for correct padding around a marker (Bangalore) and correct padding around MyLocationView.
- * </p>
*/
public class MapPaddingActivity extends AppCompatActivity {
@@ -96,24 +91,7 @@ public class MapPaddingActivity extends AppCompatActivity {
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();
- }
- }
-
private void moveToBangalore() {
- toggleGps(false);
-
LatLng bangalore = new LatLng(12.9810816, 77.6368034);
CameraPosition cameraPosition = new CameraPosition.Builder()
.zoom(16)
@@ -129,11 +107,6 @@ public class MapPaddingActivity extends AppCompatActivity {
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case R.id.action_user_tracking:
- if (mapboxMap != null) {
- toggleGps(true);
- }
- return true;
case R.id.action_bangalore:
if (mapboxMap != null) {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java
index 609910892b..97b4fbf6af 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/BuildingFillExtrusionActivity.java
@@ -8,8 +8,7 @@ import android.view.MenuItem;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.style.functions.Function;
-import com.mapbox.mapboxsdk.style.functions.stops.IdentityStops;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.FillExtrusionLayer;
import com.mapbox.mapboxsdk.style.layers.Property;
import com.mapbox.mapboxsdk.style.layers.PropertyFactory;
@@ -17,7 +16,9 @@ import com.mapbox.mapboxsdk.style.light.Light;
import com.mapbox.mapboxsdk.style.light.Position;
import com.mapbox.mapboxsdk.testapp.R;
-import static com.mapbox.mapboxsdk.style.layers.Filter.eq;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionBase;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionColor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionHeight;
@@ -53,12 +54,12 @@ public class BuildingFillExtrusionActivity extends AppCompatActivity {
private void setupBuildings() {
FillExtrusionLayer fillExtrusionLayer = new FillExtrusionLayer("3d-buildings", "composite");
fillExtrusionLayer.setSourceLayer("building");
- fillExtrusionLayer.setFilter(eq("extrude", "true"));
+ fillExtrusionLayer.setFilter(eq(get("extrude"), literal("true")));
fillExtrusionLayer.setMinZoom(15);
fillExtrusionLayer.setProperties(
fillExtrusionColor(Color.LTGRAY),
- fillExtrusionHeight(Function.property("height", new IdentityStops<Float>())),
- fillExtrusionBase(Function.property("min_height", new IdentityStops<Float>())),
+ fillExtrusionHeight(Expression.get("height")),
+ fillExtrusionBase(Expression.get("min_height")),
fillExtrusionOpacity(0.9f)
);
mapboxMap.addLayer(fillExtrusionLayer);
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 6aa8777777..9437422d84 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
@@ -13,6 +13,7 @@ import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
import com.mapbox.mapboxsdk.style.layers.LineLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
@@ -23,7 +24,10 @@ import java.net.URL;
import timber.log.Timber;
-import static com.mapbox.mapboxsdk.style.layers.Filter.in;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.array;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.has;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleColor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleRadius;
@@ -117,7 +121,7 @@ public class CircleLayerActivity extends AppCompatActivity implements View.OnCli
}
private void applyBusRouteFilterToBusStopSource() {
- layer.setFilter(in("number", (Object[]) Data.STOPS_FOR_ROUTE));
+ layer.setFilter(has(Expression.toString(get("number")), array(literal(Data.STOPS_FOR_ROUTE))));
}
private void addBusRouteSource() {
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.java
index cbac62bcc1..dae0714d42 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/DataDrivenStyleActivity.java
@@ -23,16 +23,18 @@ import java.io.IOException;
import timber.log.Timber;
-import static com.mapbox.mapboxsdk.style.expressions.Expression.color;
import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential;
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate;
import static com.mapbox.mapboxsdk.style.expressions.Expression.linear;
import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
import static com.mapbox.mapboxsdk.style.expressions.Expression.match;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.rgb;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.rgba;
import static com.mapbox.mapboxsdk.style.expressions.Expression.step;
import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.color;
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;
@@ -165,7 +167,6 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
}
}
-
private void addExponentialZoomFunction() {
Timber.i("Add exponential zoom function");
FillLayer layer = mapboxMap.getLayerAs("water");
@@ -191,10 +192,10 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
layer.setProperties(
fillColor(
step(zoom(),
- color(Color.CYAN),
- stop(1, color(Color.RED)),
- stop(5, color(Color.BLUE)),
- stop(10, color(Color.GREEN))
+ rgba(0.0f, 255.0f, 255.0f, 1.0f),
+ stop(1, rgba(255.0f, 0.0f, 0.0f, 1.0f)),
+ stop(5, rgba(0.0f, 0.0f, 255.0f, 1.0f)),
+ stop(10, rgba(0.0f, 255.0f, 0.0f, 1.0f))
)
)
);
@@ -211,9 +212,9 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
interpolate(
exponential(0.5f),
get("stroke-width"),
- stop(1f, color(Color.RED)),
- stop(5f, color(Color.BLUE)),
- stop(10f, color(Color.GREEN))
+ stop(1f, rgba(255.0f, 0.0f, 0.0f, 1.0f)),
+ stop(5f, rgba(0.0f, 0.0f, 255.0f, 1.0f)),
+ stop(10f, rgba(0.0f, 255.0f, 0.0f, 1.0f))
)
)
);
@@ -229,10 +230,10 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
fillColor(
match(
get("name"),
- literal("Westerpark"), color(Color.RED),
- literal("Jordaan"), color(Color.BLUE),
- literal("Prinseneiland"), color(Color.GREEN),
- color(Color.CYAN)
+ literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
+ literal("Jordaan"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
+ literal("Prinseneiland"), rgba(0.0f, 255.0f, 0.0f, 1.0f),
+ rgba(0.0f, 255.0f, 255.0f, 1.0f)
)
)
);
@@ -261,10 +262,10 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
fillColor(
step(
get("stroke-width"),
- color(Color.CYAN),
- stop(1f, color(Color.RED)),
- stop(2f, color(Color.BLUE)),
- stop(3f, color(Color.GREEN))
+ rgba(0.0f, 255.0f, 255.0f, 1.0f),
+ stop(1f, rgba(255.0f, 0.0f, 0.0f, 1.0f)),
+ stop(2f, rgba(0.0f, 0.0f, 255.0f, 1.0f)),
+ stop(3f, rgba(0.0f, 255.0f, 0.0f, 1.0f))
)
)
);
@@ -283,24 +284,24 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
zoom(),
stop(12, step(
get("stroke-width"),
- color(Color.BLACK),
- stop(1f, color(Color.RED)),
- stop(2f, color(Color.WHITE)),
- stop(3f, color(Color.BLUE))
+ rgba(255.0f, 255.0f, 255.0f, 1.0f),
+ stop(1f, rgba(255.0f, 0.0f, 0.0f, 1.0f)),
+ stop(2f, rgba(0.0f, 0.0f, 0.0f, 1.0f)),
+ stop(3f, rgba(0.0f, 0.0f, 255.0f, 1.0f))
)),
stop(15, step(
get("stroke-width"),
- color(Color.BLACK),
- stop(1f, color(Color.YELLOW)),
- stop(2f, color(Color.LTGRAY)),
- stop(3f, color(Color.CYAN))
+ rgba(255.0f, 255.0f, 255.0f, 1.0f),
+ stop(1f, rgba(255.0f, 255.0f, 0.0f, 1.0f)),
+ stop(2f, rgba(211.0f, 211.0f, 211.0f, 1.0f)),
+ stop(3f, rgba(0.0f, 255.0f, 255.0f, 1.0f))
)),
stop(18, step(
get("stroke-width"),
- color(Color.BLACK),
- stop(1f, color(Color.WHITE)),
- stop(2f, color(Color.GRAY)),
- stop(3f, color(Color.GREEN)))
+ rgba(255.0f, 255.0f, 255.0f, 1.0f),
+ stop(1f, rgba(0.0f, 0.0f, 0.0f, 1.0f)),
+ stop(2f, rgba(128.0f, 128.0f, 128.0f, 1.0f)),
+ stop(3f, rgba(0.0f, 255.0f, 0.0f, 1.0f)))
)
)
)
@@ -320,24 +321,24 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
zoom(),
stop(12, step(
get("stroke-width"),
- color(Color.BLACK),
- stop(1f, color(Color.RED)),
- stop(2f, color(Color.WHITE)),
- stop(3f, color(Color.BLUE))
+ rgba(255.0f, 255.0f, 255.0f, 1.0f),
+ stop(1f, rgba(255.0f, 0.0f, 0.0f, 1.0f)),
+ stop(2f, rgba(0.0f, 0.0f, 0.0f, 1.0f)),
+ stop(3f, rgba(0.0f, 0.0f, 255.0f, 1.0f))
)),
stop(15, step(
get("stroke-width"),
- color(Color.BLACK),
- stop(1f, color(Color.YELLOW)),
- stop(2f, color(Color.LTGRAY)),
- stop(3f, color(Color.CYAN))
+ rgba(255.0f, 255.0f, 255.0f, 1.0f),
+ stop(1f, rgba(255.0f, 255.0f, 0.0f, 1.0f)),
+ stop(2f, rgba(211.0f, 211.0f, 211.0f, 1.0f)),
+ stop(3f, rgba(0.0f, 255.0f, 255.0f, 1.0f))
)),
stop(18, step(
get("stroke-width"),
- color(Color.BLACK),
- stop(1f, color(Color.WHITE)),
- stop(2f, color(Color.GRAY)),
- stop(3f, color(Color.GREEN))
+ rgba(255.0f, 255.0f, 255.0f, 1.0f),
+ stop(1f, rgba(0.0f, 0.0f, 0.0f, 1.0f)),
+ stop(2f, rgba(128.0f, 128.0f, 128.0f, 1.0f)),
+ stop(3f, rgba(0.0f, 255.0f, 0.0f, 1.0f))
))
)
)
@@ -353,89 +354,89 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
layer.setProperties(
fillColor(
step(zoom(),
- color(Color.BLACK),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f),
stop(7f, match(
get("name"),
- literal("Westerpark"), color(Color.RED),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(8f, match(
get("name"),
- literal("Westerpark"), color(Color.BLUE),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(9f, match(
get("name"),
- literal("Westerpark"), color(Color.RED),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(10f, match(
get("name"),
- literal("Westerpark"), color(Color.BLUE),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(11f, match(
get("name"),
- literal("Westerpark"), color(Color.RED),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(12f, match(
get("name"),
- literal("Westerpark"), color(Color.BLUE),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(13f, match(
get("name"),
- literal("Westerpark"), color(Color.RED),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(14f, match(
get("name"),
- literal("Westerpark"), color(Color.BLUE),
- literal("Jordaan"), color(Color.GREEN),
- literal("PrinsenEiland"), color(Color.WHITE),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
+ literal("Jordaan"), rgba(0.0f, 255.0f, 0.0f, 1.0f),
+ literal("PrinsenEiland"), rgba(0.0f, 0.0f, 0.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(15f, match(
get("name"),
- literal("Westerpark"), color(Color.RED),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(16f, match(
get("name"),
- literal("Westerpark"), color(Color.BLUE),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(17f, match(
get("name"),
- literal("Westerpark"), color(Color.RED),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(18f, match(
get("name"),
- literal("Westerpark"), color(Color.BLUE),
- literal("Jordaan"), color(Color.CYAN),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
+ literal("Jordaan"), rgba(0.0f, 255.0f, 255.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(19f, match(
get("name"),
- literal("Westerpark"), color(Color.RED),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(20f, match(
get("name"),
- literal("Westerpark"), color(Color.BLUE),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(21f, match(
get("name"),
- literal("Westerpark"), color(Color.RED),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(255.0f, 0.0f, 0.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
)),
stop(22f, match(
get("name"),
- literal("Westerpark"), color(Color.BLUE),
- color(Color.BLACK)
+ literal("Westerpark"), rgba(0.0f, 0.0f, 255.0f, 1.0f),
+ rgba(255.0f, 255.0f, 255.0f, 1.0f)
))
)
)
@@ -461,8 +462,8 @@ public class DataDrivenStyleActivity extends AppCompatActivity {
// Add a fill layer
mapboxMap.addLayer(new FillLayer(AMSTERDAM_PARKS_LAYER, source.getId())
.withProperties(
- fillColor(Color.BLACK),
- fillOutlineColor(Color.BLUE),
+ fillColor(color(Color.GREEN)),
+ fillOutlineColor(rgb(0, 0, 255)),
fillAntialias(true)
)
);
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionActivity.java
index 15d7024abf..b7f6b10b0d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/FillExtrusionActivity.java
@@ -4,6 +4,7 @@ import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
+import com.mapbox.geojson.Point;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
@@ -14,6 +15,9 @@ import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.geojson.Polygon;
+import java.util.Arrays;
+import java.util.List;
+
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionColor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionHeight;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.fillExtrusionOpacity;
@@ -35,30 +39,17 @@ public class FillExtrusionActivity extends AppCompatActivity {
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(map -> {
mapboxMap = map;
- Polygon domTower = Polygon.fromLngLats(new double[][][] {
- new double[][] {
- new double[] {
- 5.12112557888031,
- 52.09071040847704
- },
- new double[] {
- 5.121227502822875,
- 52.09053901776669
- },
- new double[] {
- 5.121484994888306,
- 52.090601641371805
- },
- new double[] {
- 5.1213884353637695,
- 52.090766439912635
- },
- new double[] {
- 5.12112557888031,
- 52.09071040847704
- }
- }
- });
+ List<List<Point>> lngLats = Arrays.asList(
+ Arrays.asList(
+ Point.fromLngLat(5.12112557888031, 52.09071040847704),
+ Point.fromLngLat(5.121227502822875, 52.09053901776669),
+ Point.fromLngLat(5.121484994888306, 52.090601641371805),
+ Point.fromLngLat(5.1213884353637695, 52.090766439912635),
+ Point.fromLngLat(5.12112557888031, 52.09071040847704)
+ )
+ );
+
+ Polygon domTower = Polygon.fromLngLats(lngLats);
GeoJsonSource source = new GeoJsonSource("extrusion-source", domTower);
map.addSource(source);
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 8664979292..655d4a8936 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
@@ -10,6 +10,7 @@ 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.style.expressions.Expression;
import com.mapbox.mapboxsdk.style.layers.CircleLayer;
import com.mapbox.mapboxsdk.style.layers.SymbolLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonOptions;
@@ -21,9 +22,12 @@ import java.net.URL;
import timber.log.Timber;
-import static com.mapbox.mapboxsdk.style.layers.Filter.all;
-import static com.mapbox.mapboxsdk.style.layers.Filter.gte;
-import static com.mapbox.mapboxsdk.style.layers.Filter.lt;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.all;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.gte;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.lt;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.toNumber;
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;
@@ -124,7 +128,7 @@ public class GeoJsonClusteringActivity extends AppCompatActivity {
)
);
} catch (MalformedURLException malformedUrlException) {
- Timber.e(malformedUrlException,"That's not an url... ");
+ Timber.e(malformedUrlException, "That's not an url... ");
}
// Add unclustered layer
@@ -145,10 +149,15 @@ public class GeoJsonClusteringActivity extends AppCompatActivity {
circleColor(layers[i][1]),
circleRadius(18f)
);
+
+ Expression pointCount = toNumber(get("point_count"));
circles.setFilter(
i == 0
- ? gte("point_count", layers[i][0]) :
- all(gte("point_count", layers[i][0]), lt("point_count", layers[i - 1][0]))
+ ? gte(pointCount, literal(layers[i][0])) :
+ all(
+ gte(pointCount, literal(layers[i][0])),
+ lt(pointCount, literal(layers[i - 1][0]))
+ )
);
mapboxMap.addLayer(circles);
}
@@ -156,7 +165,7 @@ public class GeoJsonClusteringActivity extends AppCompatActivity {
// Add the count labels
SymbolLayer count = new SymbolLayer("count", "earthquakes");
count.setProperties(
- textField("{point_count}"),
+ textField(get("point_count")),
textSize(12f),
textColor(Color.WHITE)
);
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/HeatmapLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/HeatmapLayerActivity.java
index b42734ea67..52509e3297 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/HeatmapLayerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/HeatmapLayerActivity.java
@@ -16,6 +16,7 @@ import java.net.URL;
import timber.log.Timber;
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.heatmapDensity;
import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate;
import static com.mapbox.mapboxsdk.style.expressions.Expression.linear;
import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
@@ -28,6 +29,7 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.circleOpacity;
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.circleStrokeWidth;
+import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.heatmapColor;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.heatmapIntensity;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.heatmapOpacity;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.heatmapRadius;
@@ -51,7 +53,6 @@ public class HeatmapLayerActivity extends AppCompatActivity {
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_heatmaplayer);
-
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(map -> {
@@ -76,11 +77,20 @@ public class HeatmapLayerActivity extends AppCompatActivity {
layer.setSourceLayer(HEATMAP_LAYER_SOURCE);
layer.setProperties(
- // TODO add heatmap color https://github.com/mapbox/mapbox-gl-native/issues/11172
// Color ramp for heatmap. Domain is 0 (low) to 1 (high).
// Begin color ramp at 0-stop with a 0-transparancy color
// to create a blur-like effect.
- //heatmapColor(),
+ heatmapColor(
+ interpolate(
+ linear(), heatmapDensity(),
+ literal(0), rgba(33, 102, 172, 0),
+ literal(0.2), rgb(103, 169, 207),
+ literal(0.4), rgb(209, 229, 240),
+ literal(0.6), rgb(253, 219, 199),
+ literal(0.8), rgb(239, 138, 98),
+ literal(1), rgb(178, 24, 43)
+ )
+ ),
// Increase the heatmap weight based on frequency and property magnitude
heatmapWeight(
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 6eb4772b15..f49d80d704 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
@@ -31,7 +31,6 @@ import com.mapbox.mapboxsdk.style.sources.VectorSource;
import com.mapbox.mapboxsdk.testapp.R;
import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
-
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
@@ -39,15 +38,18 @@ import java.util.List;
import timber.log.Timber;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.all;
import static com.mapbox.mapboxsdk.style.expressions.Expression.color;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
import static com.mapbox.mapboxsdk.style.expressions.Expression.exponential;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.gte;
import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.lt;
import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.toNumber;
import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom;
-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;
-import static com.mapbox.mapboxsdk.style.layers.Filter.lt;
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.SYMBOL_PLACEMENT_POINT;
@@ -295,7 +297,7 @@ public class RuntimeStyleActivity extends AppCompatActivity {
);
// Only show me parks (except westerpark with stroke-width == 3)
- layer.setFilter(all(eq("type", "park"), eq("stroke-width", 2)));
+ layer.setFilter(all(eq(get("type"), literal("park")), eq(get("stroke-width"), literal(3))));
mapboxMap.addLayerBelow(layer, "building");
// layer.setPaintProperty(fillColor(Color.RED)); // XXX But not after the object is attached
@@ -345,7 +347,7 @@ public class RuntimeStyleActivity extends AppCompatActivity {
);
// Only show me parks
- layer.setFilter(all(eq("type", "park")));
+ layer.setFilter(all(eq(get("type"), literal("park"))));
mapboxMap.addLayer(layer);
@@ -499,7 +501,7 @@ public class RuntimeStyleActivity extends AppCompatActivity {
FillLayer states = (FillLayer) mapboxMap.getLayer("states");
if (states != null) {
- states.setFilter(eq("name", "Texas"));
+ states.setFilter(eq(get("name"), literal("Texas")));
states.setFillOpacityTransition(new TransitionOptions(2500, 0));
states.setFillColorTransition(new TransitionOptions(2500, 0));
states.setProperties(
@@ -527,7 +529,7 @@ public class RuntimeStyleActivity extends AppCompatActivity {
LineLayer counties = (LineLayer) mapboxMap.getLayer("counties");
if (counties != null) {
- counties.setFilter(eq("NAME10", "Washington"));
+ counties.setFilter(eq(get("NAME10"), "Washington"));
counties.setProperties(
lineColor(Color.RED),
@@ -555,7 +557,10 @@ public class RuntimeStyleActivity extends AppCompatActivity {
FillLayer regions = (FillLayer) mapboxMap.getLayer("regions");
if (regions != null) {
- regions.setFilter(all(gte("HRRNUM", 200), lt("HRRNUM", 300)));
+ regions.setFilter(all(
+ gte(toNumber(get("HRRNUM")), literal(200)),
+ lt(toNumber(get("HRRNUM")), literal(300)))
+ );
regions.setProperties(
fillColor(Color.BLUE),
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java
index ca4176be6e..f32aa5faf8 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/SymbolGeneratorActivity.java
@@ -20,15 +20,15 @@ import com.mapbox.geojson.FeatureCollection;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.style.layers.Filter;
+import com.mapbox.mapboxsdk.style.expressions.Expression;
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.mapboxsdk.testapp.utils.ResourceUtils;
-
import java.io.IOException;
+import java.lang.ref.WeakReference;
import java.util.HashMap;
import java.util.List;
@@ -37,11 +37,19 @@ import timber.log.Timber;
import static com.mapbox.mapboxsdk.style.expressions.Expression.concat;
import static com.mapbox.mapboxsdk.style.expressions.Expression.division;
import static com.mapbox.mapboxsdk.style.expressions.Expression.downcase;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.eq;
import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.match;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.number;
import static com.mapbox.mapboxsdk.style.expressions.Expression.pi;
import static com.mapbox.mapboxsdk.style.expressions.Expression.product;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.rgba;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.step;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.string;
import static com.mapbox.mapboxsdk.style.expressions.Expression.upcase;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom;
import static com.mapbox.mapboxsdk.style.layers.Property.ICON_ANCHOR_BOTTOM;
import static com.mapbox.mapboxsdk.style.layers.Property.TEXT_ANCHOR_TOP;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconAllowOverlap;
@@ -50,6 +58,7 @@ import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconImage;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconOffset;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.iconSize;
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.textSize;
@@ -115,8 +124,8 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR
return true;
} else if (item.getItemId() == R.id.menu_action_filter) {
SymbolLayer layer = mapboxMap.getLayerAs(LAYER_ID);
- layer.setFilter(Filter.eq(FEATURE_RANK, 1));
- //layer.setFilter(eq(get(FEATURE_RANK), 1));
+ layer.setFilter(eq(get(FEATURE_RANK), literal(1)));
+ Timber.e("Filter that was set: %s", layer.getFilter());
return true;
}
return super.onOptionsItemSelected(item);
@@ -196,27 +205,32 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR
private static class LoadDataTask extends AsyncTask<Void, Void, FeatureCollection> {
- private SymbolGeneratorActivity activity;
+ private WeakReference<SymbolGeneratorActivity> activity;
LoadDataTask(SymbolGeneratorActivity activity) {
- this.activity = activity;
+ this.activity = new WeakReference<>(activity);
}
@Override
protected FeatureCollection doInBackground(Void... params) {
- try {
- // read local geojson from raw folder
- String tinyCountriesJson = ResourceUtils.readRawResource(activity, R.raw.tiny_countries);
- return FeatureCollection.fromJson(tinyCountriesJson);
-
- } catch (IOException exception) {
- return null;
+ Context context = activity.get();
+ if (context != null) {
+ try {
+ // read local geojson from raw folder
+ String tinyCountriesJson = ResourceUtils.readRawResource(context, R.raw.tiny_countries);
+ return FeatureCollection.fromJson(tinyCountriesJson);
+
+ } catch (IOException exception) {
+ Timber.e(exception);
+ }
}
+ return null;
}
@Override
protected void onPostExecute(FeatureCollection featureCollection) {
super.onPostExecute(featureCollection);
+ SymbolGeneratorActivity activity = this.activity.get();
if (featureCollection == null || activity == null) {
return;
}
@@ -226,37 +240,74 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR
}
public void onDataLoaded(@NonNull FeatureCollection featureCollection) {
- // add a geojson to the map
- Source source = new GeoJsonSource(SOURCE_ID, featureCollection);
- mapboxMap.addSource(source);
+ // create expressions
+ Expression iconImageExpression = string(get(literal(FEATURE_ID)));
+ Expression iconSizeExpression = division(number(get(literal(FEATURE_RANK))), literal(2.0f));
+ Expression textSizeExpression = product(get(literal(FEATURE_RANK)), pi());
+ Expression textFieldExpression = concat(upcase(literal("a ")), upcase(string(get(literal(FEATURE_TYPE)))),
+ downcase(literal(" IN ")), string(get(literal(FEATURE_REGION)))
+ );
+ Expression textColorExpression = match(get(literal(FEATURE_RANK)),
+ literal(1), rgba(255, 0, 0, 1.0f),
+ literal(2), rgba(0, 0, 255.0f, 1.0f),
+ rgba(0.0f, 255.0f, 0.0f, 1.0f)
+ );
- // create layer use
- mapboxMap.addLayer(new SymbolLayer(LAYER_ID, SOURCE_ID)
- .withProperties(
+ rgba(
+ division(literal(255), get(FEATURE_RANK)),
+ literal(0.0f),
+ literal(0.0f),
+ literal(1.0f)
+ );
+ // create symbol layer
+ SymbolLayer symbolLayer = new SymbolLayer(LAYER_ID, SOURCE_ID)
+ .withProperties(
// icon configuration
- iconImage(get(literal(FEATURE_ID))),
+ iconImage(iconImageExpression),
iconAllowOverlap(false),
- iconSize(
- division(get(literal(FEATURE_RANK)), literal(2))
- ),
+ iconSize(iconSizeExpression),
iconAnchor(ICON_ANCHOR_BOTTOM),
- iconOffset(new Float[] {0.0f, -5.0f}),
+ iconOffset(step(zoom(), literal(new float[] {0f, 0f}),
+ stop(1, new Float[] {0f, 0f}),
+ stop(10, new Float[] {0f, -35f})
+ )),
// text field configuration
- textField(
- concat(
- upcase(literal("a ")),
- get(literal(FEATURE_TYPE)),
- downcase(literal(" IN ")),
- get(literal(FEATURE_REGION))
- )
- ),
- textSize(
- product(get(literal(FEATURE_RANK)), pi())
- ),
- textAnchor(TEXT_ANCHOR_TOP)
- )
+ textField(textFieldExpression),
+ textSize(textSizeExpression),
+ textAnchor(TEXT_ANCHOR_TOP),
+ textColor(textColorExpression)
+ );
+
+ // add a geojson source to the map
+ Source source = new GeoJsonSource(SOURCE_ID, featureCollection);
+ mapboxMap.addSource(source);
+
+ // add symbol layer
+ mapboxMap.addLayer(symbolLayer);
+
+ // get expressions
+ Expression iconImageExpressionResult = symbolLayer.getIconImage().getExpression();
+ Expression iconSizeExpressionResult = symbolLayer.getIconSize().getExpression();
+ Expression textSizeExpressionResult = symbolLayer.getTextSize().getExpression();
+ Expression textFieldExpressionResult = symbolLayer.getTextField().getExpression();
+ Expression textColorExpressionResult = symbolLayer.getTextColor().getExpression();
+
+ // log expressions
+ Timber.e(iconImageExpressionResult.toString());
+ Timber.e(iconSizeExpressionResult.toString());
+ Timber.e(textSizeExpressionResult.toString());
+ Timber.e(textFieldExpressionResult.toString());
+ Timber.e(textColorExpressionResult.toString());
+
+ // reset expressions
+ symbolLayer.setProperties(
+ iconImage(iconImageExpressionResult),
+ iconSize(iconSizeExpressionResult),
+ textSize(textSizeExpressionResult),
+ textField(textFieldExpressionResult),
+ textColor(textColorExpressionResult)
);
new GenerateSymbolTask(mapboxMap, this).execute(featureCollection);
@@ -265,27 +316,29 @@ public class SymbolGeneratorActivity extends AppCompatActivity implements OnMapR
private static class GenerateSymbolTask extends AsyncTask<FeatureCollection, Void, HashMap<String, Bitmap>> {
private MapboxMap mapboxMap;
- private Context context;
+ private WeakReference<Context> context;
GenerateSymbolTask(MapboxMap mapboxMap, Context context) {
this.mapboxMap = mapboxMap;
- this.context = context;
+ this.context = new WeakReference<>(context);
}
@SuppressWarnings("WrongThread")
@Override
protected HashMap<String, Bitmap> doInBackground(FeatureCollection... params) {
- FeatureCollection featureCollection = params[0];
-
HashMap<String, Bitmap> imagesMap = new HashMap<>();
- for (Feature feature : featureCollection.features()) {
- String countryName = feature.getStringProperty(FEATURE_ID);
- TextView textView = new TextView(context);
- textView.setBackgroundColor(context.getResources().getColor(R.color.blueAccent));
- textView.setPadding(10, 5, 10, 5);
- textView.setTextColor(Color.WHITE);
- textView.setText(countryName);
- imagesMap.put(countryName, SymbolGenerator.generate(textView));
+ Context context = this.context.get();
+ List<Feature> features = params[0].features();
+ if (context != null && features != null) {
+ for (Feature feature : features) {
+ String countryName = feature.getStringProperty(FEATURE_ID);
+ TextView textView = new TextView(context);
+ textView.setBackgroundColor(context.getResources().getColor(R.color.blueAccent));
+ textView.setPadding(10, 5, 10, 5);
+ textView.setTextColor(Color.WHITE);
+ textView.setText(countryName);
+ imagesMap.put(countryName, SymbolGenerator.generate(textView));
+ }
}
return imagesMap;
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java
index 180e2e726a..df06c9c42d 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/style/ZoomFunctionSymbolLayerActivity.java
@@ -22,11 +22,13 @@ import java.util.List;
import timber.log.Timber;
-import static com.mapbox.mapboxsdk.style.functions.Function.property;
-import static com.mapbox.mapboxsdk.style.functions.Function.zoom;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stop.stop;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.categorical;
-import static com.mapbox.mapboxsdk.style.functions.stops.Stops.interval;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.get;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.interpolate;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.linear;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.literal;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.stop;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.switchCase;
+import static com.mapbox.mapboxsdk.style.expressions.Expression.zoom;
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;
@@ -101,20 +103,16 @@ public class ZoomFunctionSymbolLayerActivity extends AppCompatActivity {
layer = new SymbolLayer(LAYER_ID, SOURCE_ID);
layer.setProperties(
iconImage(
- zoom(
- interval(
- stop(ZOOM_STOP_MIN_VALUE, iconImage(BUS_MAKI_ICON_ID)),
- stop(ZOOM_STOP_MAX_VALUE, iconImage(CAFE_MAKI_ICON_ID))
- )
- )
+ interpolate(
+ linear(), zoom(),
+ stop(ZOOM_STOP_MIN_VALUE, BUS_MAKI_ICON_ID),
+ stop(ZOOM_STOP_MAX_VALUE, CAFE_MAKI_ICON_ID)
+ )
),
iconSize(
- property(
- KEY_PROPERTY_SELECTED,
- categorical(
- stop(true, iconSize(3.0f)),
- stop(false, iconSize(1.0f))
- )
+ switchCase(
+ get(KEY_PROPERTY_SELECTED), literal(3.0f),
+ literal(1.0f)
)
),
iconAllowOverlap(true)
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewResizeActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewResizeActivity.java
index 788003d867..69bab45ce0 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewResizeActivity.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/textureview/TextureViewResizeActivity.java
@@ -95,4 +95,4 @@ public class TextureViewResizeActivity extends AppCompatActivity {
mapView.onLowMemory();
}
-}
+} \ No newline at end of file
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/textureview/TextureViewTransparentBackgroundActivity.java
index ea3a6f14bc..15da018b0e 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/textureview/TextureViewTransparentBackgroundActivity.java
@@ -1,52 +1,55 @@
-package com.mapbox.mapboxsdk.testapp.activity.userlocation;
+package com.mapbox.mapboxsdk.testapp.activity.textureview;
import android.os.Bundle;
-import android.support.design.widget.FloatingActionButton;
+import android.support.v7.app.AppCompatActivity;
+import android.widget.ImageView;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.testapp.R;
+import com.mapbox.mapboxsdk.testapp.utils.ResourceUtils;
+
+import java.io.IOException;
import timber.log.Timber;
/**
- * Test activity showcasing toggling the user location on the map.
+ * Example showcasing how to create a TextureView with a transparent background.
*/
-public class MyLocationToggleActivity extends BaseLocationActivity {
+public class TextureViewTransparentBackgroundActivity extends AppCompatActivity {
private MapView mapView;
private MapboxMap mapboxMap;
- private FloatingActionButton locationToggleFab;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_my_location_toggle);
+ setContentView(R.layout.activity_textureview_transparent);
+ setupBackground();
+ setupMapView(savedInstanceState);
+ }
+
+ private void setupBackground() {
+ ImageView imageView = (ImageView) findViewById(R.id.imageView);
+ imageView.setImageResource(R.drawable.water);
+ imageView.setScaleType(ImageView.ScaleType.FIT_XY);
+ }
+ private void setupMapView(Bundle savedInstanceState) {
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(map -> mapboxMap = map);
+ mapView.getMapAsync(map -> {
+ mapboxMap = map;
- locationToggleFab = (FloatingActionButton) findViewById(R.id.fabLocationToggle);
- locationToggleFab.setOnClickListener(view -> {
- if (mapboxMap != null) {
- toggleGps(!mapboxMap.isMyLocationEnabled());
+ try {
+ map.setStyleJson(ResourceUtils.readRawResource(getApplicationContext(), R.raw.no_bg_style));
+ } catch (IOException exception) {
+ Timber.e(exception);
}
});
}
@Override
- protected void enableLocation(boolean enabled) {
- Timber.e("Enabling location: %s", enabled);
- mapboxMap.setMyLocationEnabled(enabled);
- if (enabled) {
- locationToggleFab.setImageResource(R.drawable.ic_location_disabled);
- } else {
- locationToggleFab.setImageResource(R.drawable.ic_my_location);
- }
- }
-
- @Override
protected void onStart() {
super.onStart();
mapView.onStart();
@@ -88,4 +91,4 @@ public class MyLocationToggleActivity extends BaseLocationActivity {
mapView.onLowMemory();
}
-}
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/BaseLocationActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/BaseLocationActivity.java
deleted file mode 100644
index eec26cc9a7..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/BaseLocationActivity.java
+++ /dev/null
@@ -1,66 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.activity.userlocation;
-
-import android.os.Build;
-import android.os.Bundle;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.annotation.UiThread;
-import android.support.design.widget.Snackbar;
-import android.support.v7.app.AppCompatActivity;
-import android.text.TextUtils;
-
-import com.mapbox.android.core.permissions.PermissionsListener;
-import com.mapbox.android.core.permissions.PermissionsManager;
-
-import java.util.List;
-
-/**
- * Base class for location aware activities.
- */
-public abstract class BaseLocationActivity extends AppCompatActivity implements PermissionsListener {
-
- private PermissionsManager permissionsManager;
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- permissionsManager = new PermissionsManager(this);
- }
-
- @UiThread
- protected final void toggleGps(boolean enableGps) {
- if (enableGps) {
- if (!isRuntimePermissionsRequired()) {
- permissionsManager.requestLocationPermissions(this);
- } else {
- enableLocation(true);
- }
- } else {
- enableLocation(false);
- }
- }
-
- @Override
- public void onExplanationNeeded(List<String> list) {
- Snackbar.make(
- findViewById(android.R.id.content),
- TextUtils.join("", list.toArray()),
- Snackbar.LENGTH_SHORT).show();
- }
-
- @Override
- public void onPermissionResult(boolean isPermissionAccepted) {
- enableLocation(isPermissionAccepted);
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
- permissionsManager.onRequestPermissionsResult(requestCode, permissions, grantResults);
- }
-
- private boolean isRuntimePermissionsRequired() {
- return android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
- }
-
- protected abstract void enableLocation(boolean enabled);
-}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/CustomLocationEngineActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/CustomLocationEngineActivity.java
deleted file mode 100644
index ff2559089c..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/CustomLocationEngineActivity.java
+++ /dev/null
@@ -1,117 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.activity.userlocation;
-
-import android.os.Bundle;
-import android.support.design.widget.FloatingActionButton;
-import android.view.Menu;
-import android.view.MenuItem;
-
-import com.mapbox.mapboxsdk.Mapbox;
-import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.testapp.R;
-
-/**
- * Test activity showcasing using a custom location engine.
- */
-public class CustomLocationEngineActivity extends BaseLocationActivity {
-
- private MapView mapView;
- private MapboxMap mapboxMap;
- private FloatingActionButton locationToggleFab;
-
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_custom_location_engine);
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(map -> {
- mapboxMap = map;
- mapboxMap.setLocationSource(MockLocationEngine.getInstance());
- });
-
- locationToggleFab = (FloatingActionButton) findViewById(R.id.fabLocationToggle);
- locationToggleFab.setOnClickListener(view -> {
- if (mapboxMap != null) {
- enableLocation(!mapboxMap.isMyLocationEnabled());
- }
- });
- }
-
- @Override
- protected void enableLocation(boolean enabled) {
- mapboxMap.setMyLocationEnabled(enabled);
- if (enabled) {
- locationToggleFab.setImageResource(R.drawable.ic_location_disabled);
- } else {
- locationToggleFab.setImageResource(R.drawable.ic_my_location);
- }
- }
-
- @Override
- public boolean onCreateOptionsMenu(Menu menu) {
- getMenuInflater().inflate(R.menu.menu_location_engine, menu);
- return super.onCreateOptionsMenu(menu);
- }
-
- @Override
- public boolean onOptionsItemSelected(MenuItem item) {
- if (mapboxMap != null) {
- int itemId = item.getItemId();
- if (itemId == R.id.action_id_location_source_lost) {
- mapboxMap.setLocationSource(Mapbox.getLocationEngine());
- return true;
- } else if (itemId == R.id.action_id_location_source_mock) {
- mapboxMap.setLocationSource(MockLocationEngine.getInstance());
- return true;
- } else if (itemId == R.id.action_id_location_source_null) {
- mapboxMap.setLocationSource(null);
- return true;
- }
- }
- 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/userlocation/MockLocationEngine.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java
deleted file mode 100644
index f4fe710de1..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MockLocationEngine.java
+++ /dev/null
@@ -1,130 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.activity.userlocation;
-
-import android.animation.AnimatorListenerAdapter;
-import android.animation.TypeEvaluator;
-import android.animation.ValueAnimator;
-import android.location.Location;
-
-import com.mapbox.android.core.location.LocationEngine;
-import com.mapbox.android.core.location.LocationEngineListener;
-
-import timber.log.Timber;
-
-/**
- * Sample LocationEngine that provides mocked LOCATIONS simulating GPS updates
- */
-public class MockLocationEngine extends LocationEngine {
- private static MockLocationEngine INSTANCE;
-
- private final LocationAnimator locationAnimator;
- private boolean running;
- private static int counter;
-
- MockLocationEngine(Location start, Location end) {
- locationAnimator = new LocationAnimator(start, end, animation -> {
- for (LocationEngineListener listener : locationListeners) {
- listener.onLocationChanged((Location) animation.getAnimatedValue());
- }
- });
- }
-
- public static synchronized MockLocationEngine getInstance() {
- if (INSTANCE == null) {
- INSTANCE = new MockLocationEngine(
- MockLocationEngine.createLocation(40.416913, -3.703861),
- MockLocationEngine.createLocation(39.461643, -0.368041)
- );
- }
- return INSTANCE;
- }
-
- public static Location createLocation(double latitude, double longitude) {
- Location location = new Location(MockLocationEngine.class.getSimpleName());
- location.setLatitude(latitude);
- location.setLongitude(longitude);
- return location;
- }
-
- @Override
- public void activate() {
- // "Connection" is immediate here
- for (LocationEngineListener listener : locationListeners) {
- listener.onConnected();
- }
- }
-
- @Override
- public void deactivate() {
- }
-
- @Override
- public boolean isConnected() {
- return true; // Always connected
- }
-
- @Override
- public Location getLastLocation() {
- return null;
- }
-
- @Override
- public void requestLocationUpdates() {
- if (!running) {
- locationAnimator.start();
- running = true;
- }
- }
-
- @Override
- public void removeLocationUpdates() {
- if (running) {
- locationAnimator.stop();
- running = false;
- Timber.e("LOC %s", counter);
- }
- }
-
- @Override
- public Type obtainType() {
- return Type.MOCK;
- }
-
- private static class LocationAnimator extends AnimatorListenerAdapter {
-
- private static final long DURATION_ANIMATION = 10000;
- private final ValueAnimator locationAnimator;
- private long animationTime;
-
- LocationAnimator(Location start, Location end, ValueAnimator.AnimatorUpdateListener listener) {
- locationAnimator = ValueAnimator.ofObject(new LocationEvaluator(), start, end);
- locationAnimator.setDuration(DURATION_ANIMATION);
- locationAnimator.addUpdateListener(listener);
- locationAnimator.addListener(this);
- }
-
- void start() {
- locationAnimator.start();
- locationAnimator.setCurrentPlayTime(animationTime);
- }
-
- void stop() {
- animationTime = locationAnimator.getCurrentPlayTime();
- locationAnimator.cancel();
- }
-
- private static class LocationEvaluator implements TypeEvaluator<Location> {
-
- private Location location = new Location(MockLocationEngine.class.getSimpleName());
-
- @Override
- public Location evaluate(float fraction, Location startValue, Location endValue) {
- counter++;
- location.setLatitude(startValue.getLatitude()
- + ((endValue.getLatitude() - startValue.getLatitude()) * fraction));
- location.setLongitude(startValue.getLongitude()
- + ((endValue.getLongitude() - startValue.getLongitude()) * fraction));
- return location;
- }
- }
- }
-}
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
deleted file mode 100644
index f603050030..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationDrawableActivity.java
+++ /dev/null
@@ -1,114 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.activity.userlocation;
-
-import android.graphics.Color;
-import android.location.Location;
-import android.os.Bundle;
-import android.support.annotation.Nullable;
-import android.support.v4.content.ContextCompat;
-import android.view.View;
-import android.view.ViewGroup;
-
-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;
-import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.android.core.location.LocationEngineListener;
-
-/**
- * Test activity showcasing how to change the MyLocationView drawable.
- */
-public class MyLocationDrawableActivity extends BaseLocationActivity implements LocationEngineListener {
-
- private MapView mapView;
- private MapboxMap mapboxMap;
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_my_location_customization);
- findViewById(R.id.progress).setVisibility(View.GONE);
-
- MapboxMapOptions mapboxMapOptions = new MapboxMapOptions();
- mapboxMapOptions.styleUrl(Style.MAPBOX_STREETS);
- mapboxMapOptions.myLocationForegroundDrawable(ContextCompat.getDrawable(this, R.drawable.ic_android));
- mapboxMapOptions.myLocationBackgroundDrawable(ContextCompat.getDrawable(this, R.drawable.ic_android));
- 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(android.R.id.content);
- parent.addView(mapView);
-
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(map -> {
- mapboxMap = map;
- toggleGps(true);
- });
- }
-
- @Override
- protected void enableLocation(boolean enabled) {
- mapboxMap.setMyLocationEnabled(enabled);
- }
-
- @Override
- public void onConnected() {
- // Nothing
- }
-
- @Override
- public void onLocationChanged(Location location) {
- mapboxMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), 14));
- }
-
- @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/userlocation/MyLocationTintActivity.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java
deleted file mode 100644
index ff3c4dfbc0..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTintActivity.java
+++ /dev/null
@@ -1,181 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.activity.userlocation;
-
-import android.app.Activity;
-import android.graphics.Color;
-import android.location.Location;
-import android.os.Bundle;
-import android.support.annotation.IdRes;
-import android.support.annotation.NonNull;
-import android.support.annotation.Nullable;
-import android.support.v4.content.ContextCompat;
-import android.view.View;
-
-import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
-import com.mapbox.mapboxsdk.constants.MyLocationTracking;
-import com.mapbox.mapboxsdk.geometry.LatLng;
-import com.mapbox.mapboxsdk.maps.MapView;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.TrackingSettings;
-import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.android.core.location.LocationEngineListener;
-
-/**
- * Test activity showcasing how to tint the MyLocationView.
- */
-public class MyLocationTintActivity extends BaseLocationActivity implements LocationEngineListener {
-
- private MapView mapView;
- private MapboxMap mapboxMap;
- private boolean firstRun;
-
- @Override
- protected void onCreate(@Nullable Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_my_location_dot_color);
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(map -> {
- mapboxMap = map;
-
- // enable location updates
- toggleGps(true);
-
- // 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,
- 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);
- });
-
- // handle tint user dot button clicks
- ViewUtils.attachClickListener(
- MyLocationTintActivity.this,
- R.id.tint_user_dot_button,
- view -> {
- myLocationViewSettings.setAccuracyTintColor(
- ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapboxGreen));
- myLocationViewSettings.setForegroundTintColor(
- ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapboxGreen));
- myLocationViewSettings.setBackgroundTintColor(Color.WHITE);
- });
-
- // handle tint accuracy ring button clicks
- ViewUtils.attachClickListener(
- MyLocationTintActivity.this,
- R.id.user_accuracy_ring_tint_button,
- view -> {
- myLocationViewSettings.setAccuracyTintColor(
- ContextCompat.getColor(MyLocationTintActivity.this, R.color.accent));
- myLocationViewSettings.setForegroundTintColor(
- ContextCompat.getColor(MyLocationTintActivity.this, R.color.mapbox_blue));
- myLocationViewSettings.setBackgroundTintColor(Color.WHITE);
- });
-
- ViewUtils.attachClickListener(
- MyLocationTintActivity.this,
- R.id.user_dot_transparent_button,
- view -> {
- myLocationViewSettings.setForegroundTintColor(Color.TRANSPARENT);
- myLocationViewSettings.setBackgroundTintColor(Color.TRANSPARENT);
- }
- );
- });
-
- }
-
- @Override
- public void onConnected() {
- // Nothing
- }
-
- @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();
- 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();
- }
-
- @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
- protected 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 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);
- }
- }
- }
-}
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
deleted file mode 100644
index ffbb2c1a90..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/activity/userlocation/MyLocationTrackingModeActivity.java
+++ /dev/null
@@ -1,296 +0,0 @@
-package com.mapbox.mapboxsdk.testapp.activity.userlocation;
-
-import android.location.Location;
-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 android.view.View;
-import android.widget.AdapterView;
-import android.widget.ArrayAdapter;
-import android.widget.Spinner;
-import android.widget.Toast;
-
-import com.mapbox.mapboxsdk.Mapbox;
-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.maps.MapView;
-import com.mapbox.mapboxsdk.maps.MapboxMap;
-import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
-import com.mapbox.mapboxsdk.maps.TrackingSettings;
-import com.mapbox.mapboxsdk.maps.UiSettings;
-import com.mapbox.mapboxsdk.testapp.R;
-import com.mapbox.android.core.location.LocationEngineListener;
-
-import timber.log.Timber;
-
-/**
- * Test activity showcasing the different tracking modes the SDK exposes.
- * <p>
- * This includes MyLocationTracking/MyLocationBearingTracking and how the components can be configured to be dismissed
- * using gesture configurations.
- * </p>
- */
-public class MyLocationTrackingModeActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener,
- OnMapReadyCallback, LocationEngineListener {
-
- 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 boolean firstRun = true;
-
- 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);
- setupToolbar();
-
- mapView = (MapView) findViewById(R.id.mapView);
- mapView.onCreate(savedInstanceState);
- mapView.getMapAsync(this);
- }
-
- @Override
- public void onMapReady(MapboxMap mapboxMap) {
- MyLocationTrackingModeActivity.this.mapboxMap = mapboxMap;
-
- mapboxMap.setMyLocationEnabled(true);
- Mapbox.getLocationEngine().addLocationEngineListener(this);
- Mapbox.getLocationEngine().requestLocationUpdates();
- }
-
- @Override
- public void onConnected() {
- // Nothing
- }
-
- @Override
- public void onLocationChanged(Location location) {
- Timber.e("Location changed %s", location);
- if (firstRun) {
- setInitialLocation(location, 16);
- }
- }
-
- private void setInitialLocation(Location location, double zoom) {
- mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location), zoom));
- mapboxMap.setMyLocationEnabled(true);
- setupSpinners(mapboxMap);
- firstRun = false;
- }
-
- private void setupToolbar() {
- 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);
- }
- }
-
- private void setupSpinners(@NonNull MapboxMap mapboxMap) {
- locationSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
- bearingSpinner.setOnItemSelectedListener(MyLocationTrackingModeActivity.this);
- setCheckBoxes();
-
- mapboxMap.setOnMyLocationTrackingModeChangeListener(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(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);
- });
- }
-
- @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;
- }
- }
- }
-
- @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();
- Mapbox.getLocationEngine().removeLocationEngineListener(this);
- Mapbox.getLocationEngine().removeLocationUpdates();
- 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);
- }
- }
-}
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 d745982388..f3562b5b15 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
@@ -9,14 +9,12 @@ public class Feature implements Parcelable {
private String label;
private String description;
private String category;
- private boolean requiresLocationPermission;
- public Feature(String name, String label, String description, String category, boolean requiresLocationPermission) {
+ public Feature(String name, String label, String description, String category) {
this.name = name;
this.label = label;
this.description = description;
this.category = category;
- this.requiresLocationPermission = requiresLocationPermission;
}
private Feature(Parcel in) {
@@ -24,7 +22,6 @@ public class Feature implements Parcelable {
label = in.readString();
description = in.readString();
category = in.readString();
- requiresLocationPermission = in.readByte() != 0;
}
public String getName() {
@@ -48,10 +45,6 @@ public class Feature implements Parcelable {
return category;
}
- public boolean isRequiresLocationPermission() {
- return requiresLocationPermission;
- }
-
public int describeContents() {
return 0;
}
@@ -61,7 +54,6 @@ public class Feature implements Parcelable {
out.writeString(label);
out.writeString(description);
out.writeString(category);
- out.writeByte((byte) (requiresLocationPermission ? 1 : 0));
}
public static final Parcelable.Creator<Feature> CREATOR
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ResourceUtils.java b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ResourceUtils.java
index f0cca57e10..6b522ac210 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ResourceUtils.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/java/com/mapbox/mapboxsdk/testapp/utils/ResourceUtils.java
@@ -2,6 +2,7 @@ package com.mapbox.mapboxsdk.testapp.utils;
import android.content.Context;
import android.support.annotation.RawRes;
+import android.util.TypedValue;
import java.io.BufferedReader;
import java.io.IOException;
@@ -16,21 +17,23 @@ public class ResourceUtils {
public static String readRawResource(Context context, @RawRes int rawResource) throws IOException {
String json = "";
if (context != null) {
- InputStream is = context.getResources().openRawResource(rawResource);
Writer writer = new StringWriter();
char[] buffer = new char[1024];
- try {
+ try (InputStream is = context.getResources().openRawResource(rawResource)) {
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();
}
json = writer.toString();
}
return json;
}
+
+ public static float convertDpToPx(Context context, float dp) {
+ return TypedValue.applyDimension(
+ TypedValue.COMPLEX_UNIT_DIP, dp, context.getResources().getDisplayMetrics());
+ }
}
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxxhdpi/water.jpg b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxxhdpi/water.jpg
new file mode 100644
index 0000000000..71b758b490
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable-xxxhdpi/water.jpg
Binary files differ
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location_disabled.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location_disabled.xml
deleted file mode 100644
index 4fedff778b..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/drawable/ic_location_disabled.xml
+++ /dev/null
@@ -1,9 +0,0 @@
-<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="#FFFFFF"
- android:pathData="M20.94,11c-0.46,-4.17 -3.77,-7.48 -7.94,-7.94L13,1h-2v2.06c-1.13,0.12 -2.19,0.46 -3.16,0.97l1.5,1.5C10.16,5.19 11.06,5 12,5c3.87,0 7,3.13 7,7 0,0.94 -0.19,1.84 -0.52,2.65l1.5,1.5c0.5,-0.96 0.84,-2.02 0.97,-3.15L23,13v-2h-2.06zM3,4.27l2.04,2.04C3.97,7.62 3.25,9.23 3.06,11L1,11v2h2.06c0.46,4.17 3.77,7.48 7.94,7.94L11,23h2v-2.06c1.77,-0.2 3.38,-0.91 4.69,-1.98L19.73,21 21,19.73 4.27,3 3,4.27zM16.27,17.54C15.09,18.45 13.61,19 12,19c-3.87,0 -7,-3.13 -7,-7 0,-1.61 0.55,-3.09 1.46,-4.27l9.81,9.81z"/>
-</vector>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_custom_location_engine.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_custom_location_engine.xml
deleted file mode 100644
index e9f461c7ee..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_custom_location_engine.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<android.support.design.widget.CoordinatorLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- 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_cameraTargetLat="40.416872"
- app:mapbox_cameraTargetLng="-3.703807"
- app:mapbox_cameraZoom="4"/>
-
- <android.support.design.widget.FloatingActionButton
- android:id="@+id/fabLocationToggle"
- 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_my_location"
- tools:backgroundTint="@color/primary"/>
-
-</android.support.design.widget.CoordinatorLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_gesture_detector.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_gesture_detector.xml
new file mode 100644
index 0000000000..26c61e1639
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_gesture_detector.xml
@@ -0,0 +1,26 @@
+<?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"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context="com.mapbox.mapboxsdk.testapp.activity.camera.GestureDetectorActivity">
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:mapbox_cameraTargetLat="51.50325"
+ app:mapbox_cameraTargetLng="-0.11968"
+ app:mapbox_cameraZoom="15" />
+
+ <android.support.v7.widget.RecyclerView
+ android:id="@+id/alerts_recycler"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentLeft="true"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true"
+ android:background="#97cdcfd3" />
+
+</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_customization.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_customization.xml
deleted file mode 100644
index addfe8427b..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_customization.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<merge xmlns:android="http://schemas.android.com/apk/res/android">
-
- <android.support.v4.widget.ContentLoadingProgressBar
- android:id="@id/progress"
- style="?android:attr/progressBarStyleLarge"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"/>
-
-</merge>
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
deleted file mode 100644
index de18e265de..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_dot_color.xml
+++ /dev/null
@@ -1,62 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:mapbox="http://schemas.android.com/tools"
- 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"
- 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="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: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: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_transparent_tint"
- android:textColor="@color/white"/>
-
- </LinearLayout>
-
-</RelativeLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_toggle.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_toggle.xml
deleted file mode 100644
index 2ec35faf04..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_toggle.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<android.support.design.widget.CoordinatorLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- 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"/>
-
- <android.support.design.widget.FloatingActionButton
- android:id="@+id/fabLocationToggle"
- 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_my_location"
- tools:backgroundTint="@color/primary"/>
-
-</android.support.design.widget.CoordinatorLayout>
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
deleted file mode 100644
index 7236a944e9..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_my_location_tracking.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-<?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">
-
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:weightSum="2">
-
- <Spinner
- android:id="@+id/spinner_location"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginEnd="8dp"
- android:layout_marginRight="8dp"
- android:layout_weight="1" />
-
- <Spinner
- android:id="@+id/spinner_bearing"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_marginLeft="8dp"
- android:layout_marginStart="8dp"
- android:layout_weight="1" />
-
- </LinearLayout>
-
-
- </android.support.v7.widget.Toolbar>
-
- <com.mapbox.mapboxsdk.maps.MapView
- android:id="@+id/mapView"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- app:mapbox_myLocationTintColor="@color/primary"
- app:mapbox_myLocationAccuracyTintColor="@color/primary"
- app:mapbox_styleUrl="@string/mapbox_style_mapbox_streets"
- app:mapbox_cameraZoom="8" />
-
-</LinearLayout>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_textureview_resize.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_textureview_resize.xml
index 2baa3d39dd..b00076e779 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_textureview_resize.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_textureview_resize.xml
@@ -7,7 +7,7 @@
android:layout_height="match_parent"
android:orientation="vertical">
-
+
<com.mapbox.mapboxsdk.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_textureview_transparent.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_textureview_transparent.xml
new file mode 100644
index 0000000000..3b9ee71359
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/activity_textureview_transparent.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<android.support.design.widget.CoordinatorLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:id="@+id/coordinator_layout"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
+
+ <ImageView
+ android:id="@+id/imageView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:contentDescription="@null"/>
+
+ <com.mapbox.mapboxsdk.maps.MapView
+ android:id="@+id/mapView"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ app:mapbox_cameraTargetLat="48.507879"
+ app:mapbox_cameraTargetLng="8.363795"
+ app:mapbox_cameraZoom="2"
+ app:mapbox_renderTextureMode="true"
+ app:mapbox_renderTextureTranslucentSurface="true"
+ app:mapbox_styleUrl="mapbox://styles/agerace-globant/cja02de7193b02suvy4gpbt2c"/>
+
+</android.support.design.widget.CoordinatorLayout>
+
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_gesture_alert.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_gesture_alert.xml
new file mode 100644
index 0000000000..5fc17d049f
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/layout/item_gesture_alert.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content">
+
+ <TextView
+ android:id="@+id/alert_message"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:paddingBottom="2dp"
+ android:paddingTop="2dp"
+ android:textSize="9sp" />
+
+</FrameLayout> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_gestures.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_gestures.xml
new file mode 100644
index 0000000000..8b3a540ffa
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_gestures.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+ <item
+ android:id="@+id/menu_gesture_none"
+ android:title="None" />
+ <item
+ android:id="@+id/menu_gesture_focus_point"
+ android:title="Focus on a point" />
+ <item
+ android:id="@+id/menu_gesture_animation"
+ android:title="Turn off velocity animations" />
+</menu> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_location_engine.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_location_engine.xml
deleted file mode 100644
index dd7408df09..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_location_engine.xml
+++ /dev/null
@@ -1,20 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:mapbox="http://schemas.android.com/apk/res-auto">
-
- <item
- android:id="@+id/action_id_location_source_lost"
- android:title="@string/menuitem_title_change_location_source_lost"
- mapbox:showAsAction="never"/>
-
- <item
- android:id="@+id/action_id_location_source_mock"
- android:title="@string/menuitem_title_change_location_source_mock"
- mapbox:showAsAction="never"/>
-
- <item
- android:id="@+id/action_id_location_source_null"
- android:title="@string/menuitem_title_change_location_source_null"
- mapbox:showAsAction="never"/>
-
-</menu> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_padding.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_padding.xml
index 7132c0c2a9..f0197a9716 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_padding.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_padding.xml
@@ -2,10 +2,6 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:mapbox="http://schemas.android.com/apk/res-auto">
<item
- android:id="@+id/action_user_tracking"
- android:title="@string/my_location_tracking"
- mapbox:showAsAction="never" />
- <item
android:id="@+id/action_bangalore"
android:title="@string/bangalore"
mapbox:showAsAction="never" />
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_tracking.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_tracking.xml
deleted file mode 100644
index 940dd9c461..0000000000
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/menu/menu_tracking.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto">
-
- <group android:checkableBehavior="all">
- <item
- android:id="@+id/action_toggle_dismissible_location"
- android:checkable="true"
- android:checked="false"
- android:title="@string/menuitem_title_tracking_mode_dismiss_on_gesture"
- app:showAsAction="never" />
- <item
- android:id="@+id/action_toggle_dismissible_bearing"
- android:checkable="true"
- android:checked="false"
- android:title="@string/menuitem_title_bearing_mode_dismiss_on_gesture"
- app:showAsAction="never" />
- <item
- android:id="@+id/action_toggle_rotate_gesture_enabled"
- android:checkable="true"
- android:checked="false"
- android:title="@string/menuitem_title_rotate_gesture_enabled"
- app:showAsAction="never" />
- <item
- android:id="@+id/action_toggle_scroll_gesture_enabled"
- android:checkable="true"
- android:checked="false"
- android:title="@string/menuitem_title_scroll_gesture_enabled"
- app:showAsAction="never" />
- </group>
-
-</menu>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/raw/no_bg_style.json b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/raw/no_bg_style.json
new file mode 100644
index 0000000000..964eefc319
--- /dev/null
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/raw/no_bg_style.json
@@ -0,0 +1,43 @@
+{
+ "version": 8,
+ "name": "Land",
+ "metadata": {
+ "mapbox:autocomposite": true,
+ },
+ "sources": {
+ "composite": {
+ "url": "mapbox://mapbox.mapbox-terrain-v2",
+ "type": "vector"
+ }
+ },
+ "sprite": "mapbox://sprites/mapbox/mapbox-terrain-v2",
+ "glyphs": "mapbox://fonts/mapbox/{fontstack}/{range}.pbf",
+ "layers": [
+ {
+ "layout": {
+ "visibility": "visible"
+ },
+ "type": "fill",
+ "source": "composite",
+ "id": "admin",
+ "paint": {
+ "fill-color": "hsl(359, 100%, 50%)",
+ "fill-opacity": 1
+ },
+ "source-layer": "landcover"
+ },
+ {
+ "layout": {
+ "visibility": "visible"
+ },
+ "type": "fill",
+ "source": "composite",
+ "id": "layer-0",
+ "paint": {
+ "fill-opacity": 1,
+ "fill-color": "hsl(359, 100%, 50%)"
+ },
+ "source-layer": "Layer_0"
+ }
+ ]
+} \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml
index e7d140d7d4..04d2e8d56e 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/actions.xml
@@ -2,14 +2,7 @@
<resources>
<string name="menuitem_title_concurrent_infowindow">Concurrent Open InfoWindows</string>
<string name="menuitem_title_deselect_markers_on_tap">Deselect Markers On Tap</string>
- <string name="menuitem_title_tracking_mode_dismiss_on_gesture">Dismiss location tracking on gesture</string>
- <string name="menuitem_title_bearing_mode_dismiss_on_gesture">Dismiss bearing tracking on gesture</string>
<string name="menuitem_title_reset">Reset</string>
- <string name="menuitem_title_rotate_gesture_enabled">Enable rotate gestures</string>
- <string name="menuitem_title_scroll_gesture_enabled">Enable scroll gestures</string>
- <string name="menuitem_title_change_location_source_lost">Change to LOST location source</string>
- <string name="menuitem_title_change_location_source_mock">Change to mock location source</string>
- <string name="menuitem_title_change_location_source_null">Reset location source to null</string>
<string name="menuitem_change_icon_overlap">Toggle icon overlap</string>
<string name="menuitem_filter">Filter layer</string>
<string name="menuitem_change_location">Change location</string>
@@ -21,10 +14,6 @@
<string name="button_camera_move">Move</string>
<string name="button_camera_ease">Ease</string>
<string name="button_camera_animate">Animate</string>
- <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="button_download_region">Download region</string>
<string name="button_list_regions">List regions</string>
@@ -73,7 +62,6 @@
<string name="add_a_composite_categorical_function">Add a composite, categorical function</string>
<string name="add_a_composite_exponential_function">Add a composite, exponential function</string>
<string name="add_a_composite_interval_function">Add a composite, interval function</string>
- <string name="my_location_tracking">My Location Tracking</string>
<string name="bangalore">Bangalore</string>
<string name="list_all_layers_in_the_style">List all layers in the style</string>
<string name="list_all_sources_in_the_style">List all sources in the style</string>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/arrays.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/arrays.xml
index 94763342d2..4b7ded8e3a 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/arrays.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/arrays.xml
@@ -7,16 +7,4 @@
<item>1000</item>
<item>10000</item>
</string-array>
-
- <string-array name="user_tracking_mode">
- <item>Disabled</item>
- <item>Follow tracking</item>
- </string-array>
-
- <string-array name="user_bearing_mode">
- <item>Disabled</item>
- <item>GPS bearing</item>
- <item>Compass bearing</item>
- <!--<item>Combined mode</item>-->
- </string-array>
</resources> \ No newline at end of file
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml
index dbc6b59db6..aafeb1cd9c 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/categories.xml
@@ -10,7 +10,6 @@
<string name="category_infowindow">Info Window</string>
<string name="category_maplayout">Map Layout</string>
<string name="category_offline">Offline</string>
- <string name="category_userlocation">User Location</string>
<string name="category_style">Styling</string>
<string name="category_features">Features</string>
<string name="category_storage">Storage</string>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
index 9d44ada937..17d6ad57c6 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/descriptions.xml
@@ -1,10 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
- <string name="description_user_location_tracking">Tracks the location of the user</string>
- <string name="description_user_location_customization">Customize the location of the user</string>
- <string name="description_user_location_dot_color">Customize the user location color</string>
- <string name="description_user_location_toggle">Toggle location of the user on and off</string>
- <string name="description_custom_location_engine">Customize location engine</string>
<string name="description_custom_layer">Overlay a custom native layer on the map</string>
<string name="description_info_window_adapter">Learn how to create a custom InfoWindow</string>
<string name="description_cameraposition">CameraPosition capabilities</string>
@@ -67,8 +62,10 @@
<string name="description_textureview_debug">Use TextureView to render the map</string>
<string name="description_textureview_resize">Resize a map rendered on a TextureView</string>
<string name="description_textureview_animate">Animate a map rendered on a TextureView</string>
+ <string name="description_textureview_transparent">Enable a transparent surface on TextureView</string>
<string name="description_grid_source">Example Custom Geometry Source</string>
<string name="description_local_glyph">Suzhou using Droid Sans for Chinese glyphs</string>
<string name="description_hillshade">Example raster-dem source and hillshade layer</string>
<string name="description_heatmaplayer">Use HeatmapLayer to visualise earthquakes</string>
+ <string name="description_gesture_detector">Manipulate gestures detector\'s settings</string>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/dimens.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/dimens.xml
index 0a43af09de..9d34183435 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/dimens.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/dimens.xml
@@ -6,6 +6,5 @@
<dimen name="map_padding_bottom">256dp</dimen>
<dimen name="map_padding_right">32dp</dimen>
<dimen name="map_padding_top">0dp</dimen>
- <dimen name="locationview_background_drawable_padding">2dp</dimen>
<dimen name="navigation_drawer_width">240dp</dimen>
</resources>
diff --git a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
index 352d7884a6..3f011bd3ed 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/main/res/values/titles.xml
@@ -21,11 +21,6 @@
<string name="activity_scroll_by">Scroll By Method</string>
<string name="activity_double_map">Double Map Activity</string>
<string name="activity_snapshot">Snapshot Activity</string>
- <string name="activity_user_tracking_mode">User tracking mode</string>
- <string name="activity_user_tracking_customization">User location drawable</string>
- <string name="activity_user_dot_color">User location tint color</string>
- <string name="activity_user_location_toggle">User location toggle</string>
- <string name="activity_custom_location_engine">Custom location engine</string>
<string name="activity_custom_layer">Custom Layer</string>
<string name="activity_map_padding">Map Padding</string>
<string name="activity_debug_mode">Debug Mode</string>
@@ -67,8 +62,10 @@
<string name="activity_textureview_debug">TextureView debug</string>
<string name="activity_textureview_resize">TextureView resize</string>
<string name="activity_textureview_animate">TextureView animation</string>
+ <string name="activity_textureview_transparent">TextureView transparent background</string>
<string name="activity_grid_source">Grid Source</string>
<string name="activity_local_glyph">Local CJK glyph generation</string>
<string name="activity_hillshade">Hillshade</string>
<string name="activity_heatmaplayer">Heatmap layer</string>
+ <string name="activity_gesture_detector">Gestures detector</string>
</resources> \ No newline at end of file
diff --git a/platform/android/config.cmake b/platform/android/config.cmake
index 30182bbc06..77074dc82c 100644
--- a/platform/android/config.cmake
+++ b/platform/android/config.cmake
@@ -190,16 +190,6 @@ add_library(mbgl-android STATIC
platform/android/src/style/sources/image_source.cpp
platform/android/src/style/sources/raster_dem_source.cpp
platform/android/src/style/sources/raster_dem_source.hpp
- platform/android/src/style/functions/stop.cpp
- platform/android/src/style/functions/stop.hpp
- platform/android/src/style/functions/categorical_stops.cpp
- platform/android/src/style/functions/categorical_stops.hpp
- platform/android/src/style/functions/exponential_stops.cpp
- platform/android/src/style/functions/exponential_stops.hpp
- platform/android/src/style/functions/identity_stops.cpp
- platform/android/src/style/functions/identity_stops.hpp
- platform/android/src/style/functions/interval_stops.cpp
- platform/android/src/style/functions/interval_stops.hpp
platform/android/src/style/position.cpp
platform/android/src/style/position.hpp
platform/android/src/style/light.cpp
@@ -222,6 +212,8 @@ add_library(mbgl-android STATIC
platform/android/src/map_renderer_runnable.hpp
# Java core classes
+ platform/android/src/java/lang.cpp
+ platform/android/src/java/lang.hpp
platform/android/src/java/util.cpp
platform/android/src/java/util.hpp
@@ -238,6 +230,8 @@ add_library(mbgl-android STATIC
platform/android/src/geojson/feature_collection.hpp
platform/android/src/geojson/geometry.cpp
platform/android/src/geojson/geometry.hpp
+ platform/android/src/geojson/geometry_collection.cpp
+ platform/android/src/geojson/geometry_collection.hpp
platform/android/src/geojson/line_string.cpp
platform/android/src/geojson/line_string.hpp
platform/android/src/geojson/multi_line_string.cpp
diff --git a/platform/android/gradle/dependencies.gradle b/platform/android/gradle/dependencies.gradle
index 695cca3a29..69b0c4b97f 100644
--- a/platform/android/gradle/dependencies.gradle
+++ b/platform/android/gradle/dependencies.gradle
@@ -8,9 +8,9 @@ ext {
]
versions = [
- mapboxServices : '3.0.0-beta.2',
- mapboxTelemetry: '3.0.0-beta.1',
- mapboxGestures : '0.1.0-20180227.133736-12',
+ mapboxServices : '3.0.1',
+ mapboxTelemetry: '3.0.2',
+ mapboxGestures : '0.2.0',
supportLib : '25.4.0',
espresso : '3.0.1',
testRunner : '1.0.1',
@@ -20,14 +20,14 @@ ext {
mockito : '2.10.0',
robolectric : '3.5.1',
timber : '4.5.1',
- okhttp : '3.9.1'
+ okhttp : '3.10.0'
]
dependenciesList = [
mapboxJavaServices : "com.mapbox.mapboxsdk:mapbox-sdk-services:${versions.mapboxServices}",
mapboxJavaGeoJSON : "com.mapbox.mapboxsdk:mapbox-sdk-geojson:${versions.mapboxServices}",
mapboxAndroidTelemetry: "com.mapbox.mapboxsdk:mapbox-android-telemetry:${versions.mapboxTelemetry}",
- mapboxAndroidGestures : "com.mapbox.mapboxsdk:mapbox-android-gestures:${versions.mapboxGestures}@aar",
+ mapboxAndroidGestures : "com.mapbox.mapboxsdk:mapbox-android-gestures:${versions.mapboxGestures}",
// for testApp
mapboxJavaTurf : "com.mapbox.mapboxsdk:mapbox-sdk-turf:${versions.mapboxServices}",
@@ -55,4 +55,4 @@ ext {
leakCanaryDebug : "com.squareup.leakcanary:leakcanary-android:${versions.leakCanary}",
leakCanaryRelease : "com.squareup.leakcanary:leakcanary-android-no-op:${versions.leakCanary}"
]
-} \ No newline at end of file
+}
diff --git a/platform/android/gradle/gradle-javadoc.gradle b/platform/android/gradle/gradle-javadoc.gradle
index 39372b4378..cf7f8f743b 100644
--- a/platform/android/gradle/gradle-javadoc.gradle
+++ b/platform/android/gradle/gradle-javadoc.gradle
@@ -1,21 +1,18 @@
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")
+ source = variant.javaCompile.source
+ options.windowTitle("Mapbox Maps SDK for Android $VERSION_NAME Reference")
+ options.docTitle("Mapbox Maps SDK for Android $VERSION_NAME")
+ options.header("Mapbox Maps SDK for Android $VERSION_NAME Reference")
options.bottom("&copy; 2015&ndash;2018 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/**'
+ exclude '**/R.java', '**/BuildConfig.java'
}
}
diff --git a/platform/android/scripts/exclude-activity-gen.json b/platform/android/scripts/exclude-activity-gen.json
index b2278c9d63..157808aa51 100644
--- a/platform/android/scripts/exclude-activity-gen.json
+++ b/platform/android/scripts/exclude-activity-gen.json
@@ -27,10 +27,11 @@
"QueryRenderedFeaturesBoxHighlightActivity",
"MultiMapActivity",
"MapInDialogActivity",
- "SimpleMapActivity",
"ManualZoomActivity",
"MaxMinZoomActivity",
"ScrollByActivity",
"ZoomFunctionSymbolLayerActivity",
- "SymbolGeneratorActivity"
-] \ No newline at end of file
+ "SymbolGeneratorActivity",
+ "TextureViewTransparentBackgroundActivity",
+ "SimpleMapActivity"
+]
diff --git a/platform/android/scripts/generate-style-code.js b/platform/android/scripts/generate-style-code.js
index 6e6d3cfa67..3b0363cc19 100755
--- a/platform/android/scripts/generate-style-code.js
+++ b/platform/android/scripts/generate-style-code.js
@@ -13,6 +13,7 @@ const lightProperties = Object.keys(spec[`light`]).reduce((memo, name) => {
var property = spec[`light`][name];
property.name = name;
property['light-property'] = true;
+ property.doc = property.doc.replace(/°/g,'&#xB0;');
memo.push(property);
return memo;
}, []);
@@ -28,9 +29,6 @@ var layers = Object.keys(spec.layer.type.values).map((type) => {
}, []);
const paintProperties = Object.keys(spec[`paint_${type}`]).reduce((memo, name) => {
- // disabled for now, see https://github.com/mapbox/mapbox-gl-native/issues/11172
- if (name === 'heatmap-color') return memo;
-
spec[`paint_${type}`][name].name = name;
memo.push(spec[`paint_${type}`][name]);
return memo;
@@ -151,6 +149,24 @@ global.propertyTypeAnnotation = function propertyTypeAnnotation(property) {
}
};
+global.defaultExpressionJava = function(property) {
+ switch (property.type) {
+ case 'boolean':
+ return 'boolean';
+ case 'number':
+ return 'number';
+ case 'string':
+ return "string";
+ case 'enum':
+ return "string";
+ case 'color':
+ return 'toColor';
+ case 'array':
+ return "array";
+ default: return "string";
+ }
+}
+
global.defaultValueJava = function(property) {
if(property.name.endsWith("-pattern")) {
return '"pedestrian-polygon"';
diff --git a/platform/android/src/bitmap.cpp b/platform/android/src/bitmap.cpp
index 50088116f4..46e7253050 100644
--- a/platform/android/src/bitmap.cpp
+++ b/platform/android/src/bitmap.cpp
@@ -110,8 +110,7 @@ PremultipliedImage Bitmap::GetImage(jni::JNIEnv& env, jni::Object<Bitmap> bitmap
}
if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
- // TODO: convert
- throw std::runtime_error("bitmap decoding: bitmap format invalid");
+ bitmap = Bitmap::Copy(env, bitmap);
}
const PixelGuard guard(env, bitmap);
@@ -128,5 +127,12 @@ PremultipliedImage Bitmap::GetImage(jni::JNIEnv& env, jni::Object<Bitmap> bitmap
return { Size{ info.width, info.height }, std::move(pixels) };
}
+jni::Object<Bitmap> Bitmap::Copy(jni::JNIEnv& env, jni::Object<Bitmap> bitmap) {
+ using Signature = jni::Object<Bitmap>(jni::Object<Config>, jni::jboolean);
+ auto static method = _class.GetMethod<Signature>(env, "copy");
+ auto config = Bitmap::Config::Create(env, Bitmap::Config::Value::ARGB_8888);
+ return bitmap.Call(env, method, config, (jni::jboolean) false);
+}
+
} // namespace android
} // namespace mbgl
diff --git a/platform/android/src/bitmap.hpp b/platform/android/src/bitmap.hpp
index f64f42ae87..c4e41db1e0 100644
--- a/platform/android/src/bitmap.hpp
+++ b/platform/android/src/bitmap.hpp
@@ -43,6 +43,7 @@ public:
static PremultipliedImage GetImage(jni::JNIEnv&, jni::Object<Bitmap>);
static jni::Object<Bitmap> CreateBitmap(jni::JNIEnv&, const PremultipliedImage&);
+ static jni::Object<Bitmap> Copy(jni::JNIEnv&, jni::Object<Bitmap>);
private:
static jni::Class<Bitmap> _class;
diff --git a/platform/android/src/example_custom_layer.cpp b/platform/android/src/example_custom_layer.cpp
index f7b425c40a..e805532541 100644
--- a/platform/android/src/example_custom_layer.cpp
+++ b/platform/android/src/example_custom_layer.cpp
@@ -112,18 +112,9 @@ void checkCompileStatus(GLuint shader) {
static const GLchar * vertexShaderSource = "attribute vec2 a_pos; void main() { gl_Position = vec4(a_pos, 0, 1); }";
static const GLchar * fragmentShaderSource = "uniform highp vec4 fill_color; void main() { gl_FragColor = fill_color; }";
-class ExampleCustomLayer {
+class ExampleCustomLayer: mbgl::style::CustomLayerHost {
public:
~ExampleCustomLayer() {
- __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "~ExampleCustomLayer");
- if (program) {
- glDeleteBuffers(1, &buffer);
- glDetachShader(program, vertexShader);
- glDetachShader(program, fragmentShader);
- glDeleteShader(vertexShader);
- glDeleteShader(fragmentShader);
- glDeleteProgram(program);
- }
}
void initialize() {
@@ -158,8 +149,15 @@ public:
GL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, 8 * sizeof(GLfloat), background, GL_STATIC_DRAW));
}
- void render() {
+ void render(const mbgl::style::CustomLayerRenderParameters&) {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "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);
GL_CHECK_ERROR(glUseProgram(program));
GL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, buffer));
@@ -172,6 +170,23 @@ public:
}
+ void contextLost() {
+ __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "ContextLost");
+ program = 0;
+ }
+
+ void deinitialize() {
+ __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "DeInitialize");
+ if (program) {
+ glDeleteBuffers(1, &buffer);
+ glDetachShader(program, vertexShader);
+ glDetachShader(program, fragmentShader);
+ glDeleteShader(vertexShader);
+ glDeleteShader(fragmentShader);
+ glDeleteProgram(program);
+ }
+ }
+
GLuint program = 0;
GLuint vertexShader = 0;
GLuint fragmentShader = 0;
@@ -186,7 +201,8 @@ GLfloat ExampleCustomLayer::color[] = { 0.0f, 1.0f, 0.0f, 1.0f };
jlong JNICALL nativeCreateContext(JNIEnv*, jobject) {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeCreateContext");
- return reinterpret_cast<jlong>(new ExampleCustomLayer());
+ auto exampleCustomLayer = std::make_unique<ExampleCustomLayer>();
+ return reinterpret_cast<jlong>(exampleCustomLayer.release());
}
void JNICALL nativeSetColor(JNIEnv*, jobject, jfloat red, jfloat green, jfloat blue, jfloat alpha) {
@@ -197,25 +213,6 @@ void JNICALL nativeSetColor(JNIEnv*, jobject, jfloat red, jfloat green, jfloat b
ExampleCustomLayer::color[3] = alpha;
}
-void nativeInitialize(void *context) {
- __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeInitialize");
- reinterpret_cast<ExampleCustomLayer*>(context)->initialize();
-}
-
-void nativeRender(void *context, const mbgl::style::CustomLayerRenderParameters& /*parameters*/) {
- __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeRender");
- reinterpret_cast<ExampleCustomLayer*>(context)->render();
-}
-
-void nativeContextLost(void */*context*/) {
- __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeContextLost");
-}
-
-void nativeDeinitialize(void *context) {
- __android_log_write(ANDROID_LOG_INFO, LOG_TAG, "nativeDeinitialize");
- delete reinterpret_cast<ExampleCustomLayer*>(context);
-}
-
extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
__android_log_write(ANDROID_LOG_INFO, LOG_TAG, "OnLoad");
@@ -234,22 +231,6 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
return JNI_ERR;
}
- env->SetStaticLongField(customLayerClass,
- env->GetStaticFieldID(customLayerClass, "InitializeFunction", "J"),
- reinterpret_cast<jlong>(nativeInitialize));
-
- env->SetStaticLongField(customLayerClass,
- env->GetStaticFieldID(customLayerClass, "RenderFunction", "J"),
- reinterpret_cast<jlong>(nativeRender));
-
- env->SetStaticLongField(customLayerClass,
- env->GetStaticFieldID(customLayerClass, "ContextLostFunction", "J"),
- reinterpret_cast<jlong>(nativeContextLost));
-
- env->SetStaticLongField(customLayerClass,
- env->GetStaticFieldID(customLayerClass, "DeinitializeFunction", "J"),
- reinterpret_cast<jlong>(nativeDeinitialize));
-
return JNI_VERSION_1_6;
}
diff --git a/platform/android/src/file_source.cpp b/platform/android/src/file_source.cpp
index 42c03b0974..58a91f6cf0 100644
--- a/platform/android/src/file_source.cpp
+++ b/platform/android/src/file_source.cpp
@@ -70,14 +70,16 @@ void FileSource::resume(jni::JNIEnv&) {
activationCounter.value()++;
if (activationCounter == 1) {
- fileSource->resume();
+ fileSource->resume();
}
}
void FileSource::pause(jni::JNIEnv&) {
- activationCounter.value()--;
- if (activationCounter == 0) {
- fileSource->pause();
+ if (activationCounter) {
+ activationCounter.value()--;
+ if (activationCounter == 0) {
+ fileSource->pause();
+ }
}
}
diff --git a/platform/android/src/geojson/conversion/feature.hpp b/platform/android/src/geojson/conversion/feature.hpp
index 86aa5fc03c..8fc62a2789 100644
--- a/platform/android/src/geojson/conversion/feature.hpp
+++ b/platform/android/src/geojson/conversion/feature.hpp
@@ -182,7 +182,7 @@ struct Converter<jni::Object<android::geojson::Feature>, mbgl::Feature> {
auto properties = jni::Object<gson::JsonObject>(*convert<jni::jobject*>(env, value.properties));
// Convert geometry
- auto geometry = jni::Object<android::geojson::Geometry>(*convert<jni::jobject*>(env, value.geometry));
+ auto geometry = *convert<jni::Object<android::geojson::Geometry>>(env, value.geometry);
// Create feature
auto feature = android::geojson::Feature::fromGeometry(env, geometry, properties, jid);
diff --git a/platform/android/src/geojson/conversion/geometry.hpp b/platform/android/src/geojson/conversion/geometry.hpp
index 5d2aab4c2d..242a68df02 100644
--- a/platform/android/src/geojson/conversion/geometry.hpp
+++ b/platform/android/src/geojson/conversion/geometry.hpp
@@ -1,190 +1,24 @@
#pragma once
-#include "../../conversion/constant.hpp"
-#include "../../conversion/collection.hpp"
-
#include <mapbox/geometry.hpp>
+#include "../geometry.hpp"
#include <jni/jni.hpp>
-#include "../../jni/local_object.hpp"
namespace mbgl {
namespace android {
namespace conversion {
/**
- * Turn mapbox::geometry type into Java GeoJson Geometries
- */
-template <typename T>
-class GeometryEvaluator {
-public:
-
- jni::JNIEnv& env;
-
- /**
- * static Point fromLngLat(double longitude,double latitude)
- */
- jni::jobject* operator()(const mapbox::geometry::point<T> &geometry) const {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/Point")).release();
- static jni::jmethodID* fromLngLat = &jni::GetStaticMethodID(env, *javaClass, "fromLngLat", "(DD)Lcom/mapbox/geojson/Point;");
-
- return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromLngLat, geometry.x, geometry.y));
- }
-
- /**
- * static LineString fromLngLats(List<Point> points)
- */
- jni::jobject* operator()(const mapbox::geometry::line_string<T> &geometry) const {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/LineString")).release();
- static jni::jmethodID* fromLngLats = &jni::GetStaticMethodID(env, *javaClass, "fromLngLats", "(Ljava/util/List;)Lcom/mapbox/geojson/LineString;");
-
- // Create
- jni::LocalObject<jni::jobject> listOfPoints = jni::NewLocalObject(env, toGeoJsonListOfPoints(env, geometry));
- return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromLngLats, listOfPoints.get()));
- }
-
- /**
- * static MultiPoint fromLngLats(List<Point> points)
- */
- jni::jobject* operator()(const mapbox::geometry::multi_point<T> &geometry) const {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/MultiPoint")).release();
- static jni::jmethodID* fromLngLats = &jni::GetStaticMethodID(env, *javaClass, "fromLngLats", "(Ljava/util/List;)Lcom/mapbox/geojson/MultiPoint;");
-
- // Create
- jni::LocalObject<jni::jobject> coordinates = jni::NewLocalObject(env, toGeoJsonListOfPoints(env, geometry));
- return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromLngLats, coordinates.get()));
- }
-
- /**
- * static Polygon fromLngLats(List<List<Point>> coordinates)
- */
- jni::jobject* operator()(const mapbox::geometry::polygon<T> &geometry) const {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/Polygon")).release();
- static jni::jmethodID* fromLngLats = &jni::GetStaticMethodID(env, *javaClass, "fromLngLats", "(Ljava/util/List;)Lcom/mapbox/geojson/Polygon;");
-
- // Create
- jni::LocalObject<jni::jobject> shape = jni::NewLocalObject(env, toShape<>(env, geometry));
- return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromLngLats, shape.get()));
- }
-
- /**
- * static MultiLineString fromLngLats(List<List<Point>> points)
- */
- jni::jobject* operator()(const mapbox::geometry::multi_line_string<T> &geometry) const {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/MultiLineString")).release();
- static jni::jmethodID* fromLngLats = &jni::GetStaticMethodID(env, *javaClass, "fromLngLats", "(Ljava/util/List;)Lcom/mapbox/geojson/MultiLineString;");
-
- // Create
- jni::LocalObject<jni::jobject> shape = jni::NewLocalObject(env, toShape<>(env, geometry));
- return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromLngLats, shape.get()));
- }
-
- /**
- * MultiPolygon (double[][][][]) -> [[[D + Object array == [[[[D
- *
- * static MultiPolygon fromLngLats(List<List<List<Point>>> points)
- */
- jni::jobject* operator()(const mapbox::geometry::multi_polygon<T> &geometry) const {
- // ArrayList
- static jni::jclass* arrayListClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/ArrayList")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *arrayListClass, "<init>", "(I)V");
- static jni::jmethodID* add = &jni::GetMethodID(env, *arrayListClass, "add", "(ILjava/lang/Object;)V");
- jni::jobject* arrayList = &jni::NewObject(env, *arrayListClass, *constructor, geometry.size());
-
- for(size_t i = 0; i < geometry.size(); i = i + 1) {
- jni::LocalObject<jni::jobject> shape = jni::NewLocalObject(env, toShape<>(env, geometry.at(i)));
- jni::CallMethod<void>(env, arrayList, *add, i, shape.get());
- }
-
- // Create the MultiPolygon
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/MultiPolygon")).release();
- static jni::jmethodID* fromGeometries = &jni::GetStaticMethodID(env, *javaClass, "fromLngLats", "(Ljava/util/List;)Lcom/mapbox/geojson/MultiPolygon;");
- return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromGeometries, arrayList));
- }
-
- /**
- * GeometryCollection
- */
- jni::jobject* operator()(const mapbox::geometry::geometry_collection<T> &collection) const {
- static jni::jclass* geometryClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/Geometry")).release();
- jni::LocalObject<jni::jarray<jni::jobject>> jarray = jni::NewLocalObject(env, &jni::NewObjectArray(env, collection.size(), *geometryClass));
-
- for(size_t i = 0; i < collection.size(); i = i + 1) {
- auto& geometry = collection.at(i);
- jni::LocalObject<jni::jobject> converted = jni::NewLocalObject(env, mapbox::geometry::geometry<T>::visit(geometry, *this));
- jni::SetObjectArrayElement(env, *jarray, i, converted.get());
- }
-
- // Turn into array list and create the GeometryCollection
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/GeometryCollection")).release();
- static jni::jmethodID* fromGeometries = &jni::GetStaticMethodID(env, *javaClass, "fromGeometries", "(Ljava/util/List;)Lcom/mapbox/geojson/GeometryCollection;");
-
- jni::LocalObject<jni::jobject> list = jni::NewLocalObject(env, toArrayList<>(env, *jarray));
- return reinterpret_cast<jni::jobject*>(jni::CallStaticMethod<jni::jobject*>(env, *javaClass, *fromGeometries, list.get()));
- }
-
-private:
-
- /**
- * vector<point<T>> -> List<Point>
- */
- static jni::jobject* toGeoJsonListOfPoints(JNIEnv& env, std::vector<mapbox::geometry::point<T>> points) {
-
- // ArrayList
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/ArrayList")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(I)V");
- static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(ILjava/lang/Object;)V");
- jni::jobject* arrayList = &jni::NewObject(env, *javaClass, *constructor, points.size());
-
-
- // Point
- static jni::jclass* pointJavaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/geojson/Point")).release();
- static jni::jmethodID* fromLngLat = &jni::GetStaticMethodID(env, *pointJavaClass, "fromLngLat", "(DD)Lcom/mapbox/geojson/Point;");
-
- for(size_t i = 0; i < points.size(); i = i + 1) {
- mapbox::geometry::point<T> point = points.at(i);
- jni::LocalObject<jni::jobject> pointObject =
- jni::NewLocalObject(env, jni::CallStaticMethod<jni::jobject*>(env, *pointJavaClass, *fromLngLat, point.x, point.y));
- jni::CallMethod<void>(env, arrayList, *add, i, pointObject.get());
- }
-
- return arrayList;
- }
-
- /**
- * geometry -> List<List<Point>>
- */
- template <class SHAPE>
- static jni::jobject* toShape(JNIEnv& env, SHAPE value) {
-
- // ArrayList
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/ArrayList")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(I)V");
- static jni::jmethodID* add = &jni::GetMethodID(env, *javaClass, "add", "(ILjava/lang/Object;)V");
- jni::jobject* arrayList = &jni::NewObject(env, *javaClass, *constructor, value.size());
-
-
- for(size_t i = 0; i < value.size(); i = i + 1) {
- jni::LocalObject<jni::jobject> listOfPoints = jni::NewLocalObject(env, toGeoJsonListOfPoints(env, value.at(i)));
- jni::CallMethod<void>(env, arrayList, *add, i, listOfPoints.get());
- }
-
- return arrayList;
- }
-};
-
-/**
- * mapbox::geometry::geometry<T> -> Java GeoJson Geometry<>
+ * mapbox::geometry::geometry<T> -> Java GeoJson Geometry
*/
template <class T>
-struct Converter<jni::jobject*, mapbox::geometry::geometry<T>> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mapbox::geometry::geometry<T>& value) const {
- GeometryEvaluator<double> evaluator { env } ;
- jni::jobject* converted = mapbox::geometry::geometry<double>::visit(value, evaluator);
- return {converted};
+struct Converter<jni::Object<android::geojson::Geometry>, mapbox::geometry::geometry<T>> {
+ Result<jni::Object<android::geojson::Geometry>> operator()(jni::JNIEnv& env, const mapbox::geometry::geometry<T>& value) const {
+ return { android::geojson::Geometry::New(env, value) };
}
};
-}
-}
-}
+} // conversion
+} // android
+} // mbgl
diff --git a/platform/android/src/geojson/geometry.cpp b/platform/android/src/geojson/geometry.cpp
index ca19d8fb03..5635b5a0f5 100644
--- a/platform/android/src/geojson/geometry.cpp
+++ b/platform/android/src/geojson/geometry.cpp
@@ -6,6 +6,7 @@
#include "multi_line_string.hpp"
#include "polygon.hpp"
#include "multi_polygon.hpp"
+#include "geometry_collection.hpp"
#include <string>
@@ -13,7 +14,49 @@ namespace mbgl {
namespace android {
namespace geojson {
-mapbox::geojson::geometry Geometry::convert(jni::JNIEnv &env, jni::Object<Geometry> jGeometry) {
+/**
+ * Turn mapbox::geometry type into Java GeoJson Geometries
+ */
+class GeometryEvaluator {
+public:
+
+ jni::JNIEnv& env;
+
+ jni::Object<Geometry> operator()(const mbgl::Point<double> &geometry) const {
+ return jni::Cast(env, Point::New(env, geometry), Geometry::javaClass);
+ }
+
+ jni::Object<Geometry> operator()(const mbgl::LineString<double> &geometry) const {
+ return jni::Cast(env, LineString::New(env, geometry), Geometry::javaClass);
+ }
+
+ jni::Object<Geometry> operator()(const mbgl::MultiLineString<double> &geometry) const {
+ return jni::Cast(env, MultiLineString::New(env, geometry), Geometry::javaClass);
+ }
+
+ jni::Object<Geometry> operator()(const mbgl::MultiPoint<double> &geometry) const {
+ return jni::Cast(env, MultiPoint::New(env, geometry), Geometry::javaClass);
+ }
+
+ jni::Object<Geometry> operator()(const mbgl::Polygon<double> &geometry) const {
+ return jni::Cast(env, Polygon::New(env, geometry), Geometry::javaClass);
+ }
+
+ jni::Object<Geometry> operator()(const mbgl::MultiPolygon<double> &geometry) const {
+ return jni::Cast(env, MultiPolygon::New(env, geometry), Geometry::javaClass);
+ }
+
+ jni::Object<Geometry> operator()(const mapbox::geometry::geometry_collection<double> &geometry) const {
+ return jni::Cast(env, GeometryCollection::New(env, geometry), Geometry::javaClass);
+ }
+};
+
+jni::Object<Geometry> Geometry::New(jni::JNIEnv& env, mbgl::Geometry<double> geometry) {
+ GeometryEvaluator evaluator { env } ;
+ return mbgl::Geometry<double>::visit(geometry, evaluator);
+}
+
+mbgl::Geometry<double> Geometry::convert(jni::JNIEnv &env, jni::Object<Geometry> jGeometry) {
auto type = Geometry::getType(env, jGeometry);
if (type == Point::Type()) {
return { Point::convert(env, jni::Object<Point>(jGeometry.Get())) };
@@ -27,6 +70,8 @@ mapbox::geojson::geometry Geometry::convert(jni::JNIEnv &env, jni::Object<Geomet
return { Polygon::convert(env, jni::Object<Polygon>(jGeometry.Get())) };
} else if (type == MultiPolygon::Type()) {
return { MultiPolygon::convert(env, jni::Object<MultiPolygon>(jGeometry.Get())) };
+ } else if (type == GeometryCollection::Type()) {
+ return { GeometryCollection::convert(env, jni::Object<GeometryCollection>(jGeometry.Get())) };
}
throw std::runtime_error(std::string {"Unsupported GeoJSON type: " } + type);
diff --git a/platform/android/src/geojson/geometry.hpp b/platform/android/src/geojson/geometry.hpp
index b7f8909f6f..a1bb886683 100644
--- a/platform/android/src/geojson/geometry.hpp
+++ b/platform/android/src/geojson/geometry.hpp
@@ -1,8 +1,10 @@
#pragma once
-#include <mbgl/util/geojson.hpp>
+#include <mbgl/util/geometry.hpp>
#include <mbgl/util/noncopyable.hpp>
+#include "../java/util.hpp"
+
#include <jni/jni.hpp>
namespace mbgl {
@@ -13,7 +15,9 @@ class Geometry : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/mapbox/geojson/Geometry"; };
- static mapbox::geojson::geometry convert(jni::JNIEnv&, jni::Object<Geometry>);
+ static jni::Object<Geometry> New(jni::JNIEnv&, mbgl::Geometry<double>);
+
+ static mbgl::Geometry<double> convert(jni::JNIEnv&, jni::Object<Geometry>);
static std::string getType(jni::JNIEnv&, jni::Object<Geometry>);
diff --git a/platform/android/src/geojson/geometry_collection.cpp b/platform/android/src/geojson/geometry_collection.cpp
new file mode 100644
index 0000000000..eb3a790404
--- /dev/null
+++ b/platform/android/src/geojson/geometry_collection.cpp
@@ -0,0 +1,63 @@
+#include "geometry_collection.hpp"
+#include "../java/util.hpp"
+
+namespace mbgl {
+namespace android {
+namespace geojson {
+
+jni::Object<GeometryCollection> GeometryCollection::New(jni::JNIEnv& env, const mapbox::geometry::geometry_collection<double>& collection) {
+ // Create an array of geometries
+ auto jarray = jni::Array<jni::Object<Geometry>>::New(env, collection.size(), Geometry::javaClass);
+
+ for (size_t i = 0; i < collection.size(); i++) {
+ auto& geometry = collection.at(i);
+ auto jGeometry = Geometry::New(env, geometry);
+ jarray.Set(env, i, jGeometry);
+ jni::DeleteLocalRef(env, jGeometry);
+ }
+
+ // Turn into array list
+ auto jList = java::util::Arrays::asList(env, jarray);
+ jni::DeleteLocalRef(env, jarray);
+
+ // create the GeometryCollection
+ static auto method = javaClass.GetStaticMethod<jni::Object<GeometryCollection> (jni::Object<java::util::List>)>(env, "fromGeometries");
+ auto jCollection = javaClass.Call(env, method, jList);
+
+ jni::DeleteLocalRef(env, jList);
+ return jCollection;
+}
+
+mapbox::geometry::geometry_collection<double> GeometryCollection::convert(jni::JNIEnv &env, jni::Object<GeometryCollection> jCollection) {
+ // Get geometries
+ static auto getGeometries = javaClass.GetMethod<jni::Object<java::util::List> ()>(env, "getGeometries");
+ auto jList = jCollection.Call(env, getGeometries);
+
+ // Turn into array
+ auto jarray = java::util::List::toArray<Geometry>(env, jList);
+ jni::DeleteLocalRef(env, jList);
+
+ // Convert each geometry
+ mapbox::geometry::geometry_collection<double> collection{};
+
+ auto size = jarray.Length(env);
+ for (jni::jsize i = 0; i < size; i++) {
+ auto element = jarray.Get(env, i);
+ collection.push_back(Geometry::convert(env, element));
+ jni::DeleteLocalRef(env, element);
+ }
+
+ jni::DeleteLocalRef(env, jarray);
+ return collection;
+}
+
+void GeometryCollection::registerNative(jni::JNIEnv &env) {
+ // Lookup the class
+ javaClass = *jni::Class<GeometryCollection>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<GeometryCollection> GeometryCollection::javaClass;
+
+} // namespace geojson
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/geojson/geometry_collection.hpp b/platform/android/src/geojson/geometry_collection.hpp
new file mode 100644
index 0000000000..9ed9953b0d
--- /dev/null
+++ b/platform/android/src/geojson/geometry_collection.hpp
@@ -0,0 +1,28 @@
+#pragma once
+
+#include "geometry.hpp"
+
+#include <jni/jni.hpp>
+
+namespace mbgl {
+namespace android {
+namespace geojson {
+
+class GeometryCollection : public Geometry {
+public:
+ static constexpr auto Name() { return "com/mapbox/geojson/GeometryCollection"; };
+
+ static constexpr auto Type() { return "GeometryCollection"; };
+
+ static jni::Object<GeometryCollection> New(jni::JNIEnv&, const mapbox::geometry::geometry_collection<double>&);
+
+ static mapbox::geometry::geometry_collection<double> convert(jni::JNIEnv&, jni::Object<GeometryCollection>);
+
+ static jni::Class<GeometryCollection> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+};
+
+} // namespace geojson
+} // namespace android
+} // namespace mbgl \ No newline at end of file
diff --git a/platform/android/src/geojson/line_string.cpp b/platform/android/src/geojson/line_string.cpp
index 8eebd53550..a5f1a468ce 100644
--- a/platform/android/src/geojson/line_string.cpp
+++ b/platform/android/src/geojson/line_string.cpp
@@ -1,11 +1,22 @@
#include "line_string.hpp"
-
#include "point.hpp"
+#include "util.hpp"
+#include "../java/util.hpp"
namespace mbgl {
namespace android {
namespace geojson {
+jni::Object<LineString> LineString::New(jni::JNIEnv& env, const mbgl::LineString<double>& lineString) {
+ auto jList = asPointsList(env, lineString);
+
+ static auto method = javaClass.GetStaticMethod<jni::Object<LineString>(jni::Object<java::util::List>)>(env, "fromLngLats");
+ auto jLineString = javaClass.Call(env, method, jList);
+
+ jni::DeleteLocalRef(env, jList);
+ return jLineString;
+}
+
mapbox::geojson::line_string LineString::convert(jni::JNIEnv &env, jni::Object<LineString> jLineString) {
mapbox::geojson::line_string lineString;
diff --git a/platform/android/src/geojson/line_string.hpp b/platform/android/src/geojson/line_string.hpp
index 86033c2e6a..98dc414642 100644
--- a/platform/android/src/geojson/line_string.hpp
+++ b/platform/android/src/geojson/line_string.hpp
@@ -1,23 +1,27 @@
#pragma once
#include <mbgl/util/geojson.hpp>
+#include <mbgl/util/geometry.hpp>
#include <mbgl/util/noncopyable.hpp>
-#include <jni/jni.hpp>
-
+#include "geometry.hpp"
#include "../java/util.hpp"
+#include <jni/jni.hpp>
+
namespace mbgl {
namespace android {
namespace geojson {
-class LineString : private mbgl::util::noncopyable {
+class LineString : public Geometry {
public:
static constexpr auto Name() { return "com/mapbox/geojson/LineString"; };
static constexpr auto Type() { return "LineString"; };
+ static jni::Object<LineString> New(jni::JNIEnv&, const mbgl::LineString<double>&);
+
static mapbox::geojson::line_string convert(jni::JNIEnv&, jni::Object<LineString>);
static mapbox::geojson::line_string convert(jni::JNIEnv&, jni::Object<java::util::List/*<Point>*/>);
diff --git a/platform/android/src/geojson/multi_line_string.cpp b/platform/android/src/geojson/multi_line_string.cpp
index c748d4786f..4a6ea37dd1 100644
--- a/platform/android/src/geojson/multi_line_string.cpp
+++ b/platform/android/src/geojson/multi_line_string.cpp
@@ -1,11 +1,22 @@
#include "multi_line_string.hpp"
#include "line_string.hpp"
+#include "util.hpp"
namespace mbgl {
namespace android {
namespace geojson {
+jni::Object<MultiLineString> MultiLineString::New(jni::JNIEnv& env, const mbgl::MultiLineString<double>& multiLineString) {
+ auto jList = asPointsListsList(env, multiLineString);
+
+ static auto method = javaClass.GetStaticMethod<jni::Object<MultiLineString> (jni::Object<java::util::List>)>(env, "fromLngLats");
+ auto jMultiLineString = javaClass.Call(env, method, jList);
+
+ jni::DeleteLocalRef(env, jList);
+ return jMultiLineString;
+}
+
mapbox::geojson::multi_line_string MultiLineString::convert(jni::JNIEnv &env, jni::Object<MultiLineString> jMultiLineString) {
mapbox::geojson::multi_line_string multiLineString;
diff --git a/platform/android/src/geojson/multi_line_string.hpp b/platform/android/src/geojson/multi_line_string.hpp
index 358a6b5dda..934a0cb6b5 100644
--- a/platform/android/src/geojson/multi_line_string.hpp
+++ b/platform/android/src/geojson/multi_line_string.hpp
@@ -3,20 +3,23 @@
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/noncopyable.hpp>
-#include <jni/jni.hpp>
-
#include "../java/util.hpp"
+#include "geometry.hpp"
+
+#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace geojson {
-class MultiLineString : private mbgl::util::noncopyable {
+class MultiLineString : public Geometry {
public:
static constexpr auto Name() { return "com/mapbox/geojson/MultiLineString"; };
static constexpr auto Type() { return "MultiLineString"; };
+ static jni::Object<MultiLineString> New(jni::JNIEnv&, const mbgl::MultiLineString<double>&);
+
static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, jni::Object<MultiLineString>);
static mapbox::geojson::multi_line_string convert(jni::JNIEnv&, jni::Object<java::util::List/*<java::util::List<Point>>*/>);
diff --git a/platform/android/src/geojson/multi_point.cpp b/platform/android/src/geojson/multi_point.cpp
index 4f9ff596b2..6f62541209 100644
--- a/platform/android/src/geojson/multi_point.cpp
+++ b/platform/android/src/geojson/multi_point.cpp
@@ -8,6 +8,16 @@ namespace mbgl {
namespace android {
namespace geojson {
+jni::Object<MultiPoint> MultiPoint::New(JNIEnv& env, const mbgl::MultiPoint<double>& multiPoint) {
+ auto jList = asPointsList(env, multiPoint);
+
+ static auto method = javaClass.GetStaticMethod<jni::Object<MultiPoint>(jni::Object<java::util::List>)>(env, "fromLngLats");
+ auto jMultiPoint = javaClass.Call(env, method, jList);
+
+ jni::DeleteLocalRef(env, jList);
+ return jMultiPoint;
+}
+
mapbox::geojson::multi_point MultiPoint::convert(jni::JNIEnv &env, jni::Object<MultiPoint> jMultiPoint) {
mapbox::geojson::multi_point multiPoint;
diff --git a/platform/android/src/geojson/multi_point.hpp b/platform/android/src/geojson/multi_point.hpp
index e893e879af..cfe80cd34c 100644
--- a/platform/android/src/geojson/multi_point.hpp
+++ b/platform/android/src/geojson/multi_point.hpp
@@ -1,22 +1,26 @@
#pragma once
#include <mbgl/util/geojson.hpp>
+#include <mbgl/util/geometry.hpp>
#include <mbgl/util/noncopyable.hpp>
-#include <jni/jni.hpp>
-
+#include "geometry.hpp"
#include "../java/util.hpp"
+#include <jni/jni.hpp>
+
namespace mbgl {
namespace android {
namespace geojson {
-class MultiPoint : private mbgl::util::noncopyable {
+class MultiPoint : public Geometry {
public:
static constexpr auto Name() { return "com/mapbox/geojson/MultiPoint"; };
static constexpr auto Type() { return "MultiPoint"; };
+ static jni::Object<MultiPoint> New(jni::JNIEnv&, const mbgl::MultiPoint<double>&);
+
static mapbox::geojson::multi_point convert(jni::JNIEnv&, jni::Object<MultiPoint>);
static jni::Object<java::util::List> coordinates(jni::JNIEnv&, jni::Object<MultiPoint>);
diff --git a/platform/android/src/geojson/multi_polygon.cpp b/platform/android/src/geojson/multi_polygon.cpp
index aadba8c8a6..cc872d4955 100644
--- a/platform/android/src/geojson/multi_polygon.cpp
+++ b/platform/android/src/geojson/multi_polygon.cpp
@@ -1,11 +1,34 @@
#include "multi_polygon.hpp"
#include "polygon.hpp"
+#include "util.hpp"
namespace mbgl {
namespace android {
namespace geojson {
+jni::Object<MultiPolygon> MultiPolygon::New(JNIEnv& env, const mbgl::MultiPolygon<double>& multiPolygon) {
+ auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, multiPolygon.size(), java::util::List::javaClass);
+
+ for (size_t i = 0; i < multiPolygon.size(); i++) {
+ auto& geometry = multiPolygon.at(i);
+ auto jPolygon = asPointsListsList(env, geometry);
+ jarray.Set(env, i, jPolygon);
+ jni::DeleteLocalRef(env, jPolygon);
+ }
+
+ // Turn into array list
+ auto jList = java::util::Arrays::asList(env, jarray);
+ jni::DeleteLocalRef(env, jarray);
+
+ // create the MultiPolygon
+ static auto method = javaClass.GetStaticMethod<jni::Object<MultiPolygon> (jni::Object<java::util::List>)>(env, "fromLngLats");
+ auto jMultiPolygon = javaClass.Call(env, method, jList);
+
+ jni::DeleteLocalRef(env, jList);
+ return jMultiPolygon;
+}
+
mapbox::geojson::multi_polygon MultiPolygon::convert(jni::JNIEnv &env, jni::Object<MultiPolygon> jMultiPolygon) {
mapbox::geojson::multi_polygon multiPolygon;
diff --git a/platform/android/src/geojson/multi_polygon.hpp b/platform/android/src/geojson/multi_polygon.hpp
index 6e1dfacfc8..b4657af09d 100644
--- a/platform/android/src/geojson/multi_polygon.hpp
+++ b/platform/android/src/geojson/multi_polygon.hpp
@@ -3,20 +3,23 @@
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/noncopyable.hpp>
-#include <jni/jni.hpp>
-
#include "../java/util.hpp"
+#include "geometry.hpp"
+
+#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace geojson {
-class MultiPolygon : private mbgl::util::noncopyable {
+class MultiPolygon : public Geometry {
public:
static constexpr auto Name() { return "com/mapbox/geojson/MultiPolygon"; };
static constexpr auto Type() { return "MultiPolygon"; };
+ static jni::Object<MultiPolygon> New(jni::JNIEnv&, const mbgl::MultiPolygon<double>&);
+
static mapbox::geojson::multi_polygon convert(jni::JNIEnv&, jni::Object<MultiPolygon>);
static jni::Object<java::util::List> coordinates(jni::JNIEnv&, jni::Object<MultiPolygon>);
diff --git a/platform/android/src/geojson/point.cpp b/platform/android/src/geojson/point.cpp
index e95376cd2e..8a9656ea14 100644
--- a/platform/android/src/geojson/point.cpp
+++ b/platform/android/src/geojson/point.cpp
@@ -7,6 +7,11 @@ namespace mbgl {
namespace android {
namespace geojson {
+jni::Object<Point> Point::New(jni::JNIEnv& env, const mbgl::Point<double>& point) {
+ static auto method = javaClass.GetStaticMethod<jni::Object<Point> (jni::jdouble, jni::jdouble)>(env, "fromLngLat");
+ return javaClass.Call(env, method, point.x, point.y);
+}
+
mapbox::geojson::point Point::convert(jni::JNIEnv &env, jni::Object<Point> jPoint) {
mapbox::geojson::point point;
@@ -54,4 +59,4 @@ jni::Class<Point> Point::javaClass;
} // namespace geojson
} // namespace android
-} // namespace mbgl \ No newline at end of file
+} // namespace mbgl
diff --git a/platform/android/src/geojson/point.hpp b/platform/android/src/geojson/point.hpp
index c6412299bf..627bd1b649 100644
--- a/platform/android/src/geojson/point.hpp
+++ b/platform/android/src/geojson/point.hpp
@@ -3,20 +3,23 @@
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/noncopyable.hpp>
-#include <jni/jni.hpp>
-
#include "../java/util.hpp"
+#include "geometry.hpp"
+
+#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace geojson {
-class Point : private mbgl::util::noncopyable {
+class Point : public Geometry {
public:
static constexpr auto Name() { return "com/mapbox/geojson/Point"; };
static constexpr auto Type() { return "Point"; };
+ static jni::Object<Point> New(jni::JNIEnv&, const mbgl::Point<double>&);
+
static mapbox::geojson::point convert(jni::JNIEnv&, jni::Object<Point>);
static mapbox::geojson::point convert(jni::JNIEnv&, jni::Object<java::util::List/*<Double>*/>);
diff --git a/platform/android/src/geojson/polygon.cpp b/platform/android/src/geojson/polygon.cpp
index 30ba996640..96058b63b3 100644
--- a/platform/android/src/geojson/polygon.cpp
+++ b/platform/android/src/geojson/polygon.cpp
@@ -8,6 +8,16 @@ namespace mbgl {
namespace android {
namespace geojson {
+jni::Object<Polygon> Polygon::New(jni::JNIEnv& env, const mbgl::Polygon<double>& polygon) {
+ auto jList = asPointsListsList(env, polygon);
+
+ static auto method = javaClass.GetStaticMethod<jni::Object<Polygon> (jni::Object<java::util::List>)>(env, "fromLngLats");
+ auto jPolygon = javaClass.Call(env, method, jList);
+
+ jni::DeleteLocalRef(env, jList);
+ return jPolygon;
+}
+
mapbox::geojson::polygon Polygon::convert(jni::JNIEnv &env, jni::Object<Polygon> jPolygon) {
mapbox::geojson::polygon polygon;
diff --git a/platform/android/src/geojson/polygon.hpp b/platform/android/src/geojson/polygon.hpp
index a8b2b93827..f3c23b4d7b 100644
--- a/platform/android/src/geojson/polygon.hpp
+++ b/platform/android/src/geojson/polygon.hpp
@@ -3,20 +3,24 @@
#include <mbgl/util/geojson.hpp>
#include <mbgl/util/noncopyable.hpp>
+#include "geometry.hpp"
+#include "../java/util.hpp"
+
#include <jni/jni.hpp>
-#include "../java/util.hpp"
namespace mbgl {
namespace android {
namespace geojson {
-class Polygon : private mbgl::util::noncopyable {
+class Polygon : public Geometry {
public:
static constexpr auto Name() { return "com/mapbox/geojson/Polygon"; };
static constexpr auto Type() { return "Polygon"; };
+ static jni::Object<Polygon> New(jni::JNIEnv&, const mbgl::Polygon<double>&);
+
static mapbox::geojson::polygon convert(jni::JNIEnv &, jni::Object<Polygon>);
static mapbox::geojson::polygon convert(jni::JNIEnv&, jni::Object<java::util::List/*<java::util::List<Point>>*/>);
diff --git a/platform/android/src/geojson/util.hpp b/platform/android/src/geojson/util.hpp
index ece8e52433..5e6d90a953 100644
--- a/platform/android/src/geojson/util.hpp
+++ b/platform/android/src/geojson/util.hpp
@@ -1,5 +1,7 @@
#pragma once
+#include "point.hpp"
+
#include <type_traits>
namespace mbgl {
@@ -17,6 +19,42 @@ To convertExplicit(From&& src) {
return *reinterpret_cast<std::add_pointer_t<To>>(&src);
}
+/**
+ * Geometry -> List<Point>
+ */
+template <class T>
+static jni::Object<java::util::List> asPointsList(jni::JNIEnv& env, const T& pointsList) {
+ auto jarray = jni::Array<jni::Object<Point>>::New(env, pointsList.size(), Point::javaClass);
+
+ for (jni::jsize i = 0; i < pointsList.size(); i++) {
+ auto jPoint = Point::New(env, pointsList.at(i));
+ jarray.Set(env, i, jPoint);
+ jni::DeleteLocalRef(env, jPoint);
+ }
+
+ auto jList = java::util::Arrays::asList(env, jarray);
+ jni::DeleteLocalRef(env, jarray);
+ return jList;
+}
+
+/**
+ * Geometry -> List<List<Point>>
+ */
+template <class SHAPE>
+static jni::Object<java::util::List> asPointsListsList(JNIEnv& env, SHAPE value) {
+ auto jarray = jni::Array<jni::Object<java::util::List>>::New(env, value.size(), java::util::List::javaClass);
+
+ for (size_t i = 0; i < value.size(); i = i + 1) {
+ auto pointsList = asPointsList(env, value[i]);
+ jarray.Set(env, i, pointsList);
+ jni::DeleteLocalRef(env, pointsList);
+ }
+
+ auto jList = java::util::Arrays::asList(env, jarray);
+ jni::DeleteLocalRef(env, jarray);
+ return jList;
+}
+
} // namespace geojson
} // namespace android
} // namespace mbgl
diff --git a/platform/android/src/gson/json_array.cpp b/platform/android/src/gson/json_array.cpp
index d91e323ac9..e8852d77e9 100644
--- a/platform/android/src/gson/json_array.cpp
+++ b/platform/android/src/gson/json_array.cpp
@@ -6,7 +6,22 @@ namespace mbgl {
namespace android {
namespace gson {
-std::vector<mapbox::geometry::value> JsonArray::convert(jni::JNIEnv &env, jni::Object<JsonArray> jsonArray) {
+jni::Object<JsonArray> JsonArray::New(jni::JNIEnv& env, const std::vector<mapbox::geometry::value>& values){
+ static auto constructor = JsonArray::javaClass.GetConstructor(env);
+ static auto addMethod = JsonArray::javaClass.GetMethod<void (jni::Object<JsonElement>)>(env, "add");
+
+ auto jsonArray = JsonArray::javaClass.New(env, constructor);
+
+ for (const auto &v : values) {
+ auto jsonElement = JsonElement::New(env, v);
+ jsonArray.Call(env, addMethod, jsonElement);
+ jni::DeleteLocalRef(env, jsonElement);
+ }
+
+ return jsonArray;
+}
+
+std::vector<mapbox::geometry::value> JsonArray::convert(jni::JNIEnv& env, const jni::Object<JsonArray> jsonArray) {
std::vector<mapbox::geometry::value> values;
if (jsonArray) {
@@ -28,7 +43,7 @@ std::vector<mapbox::geometry::value> JsonArray::convert(jni::JNIEnv &env, jni::O
return values;
}
-void JsonArray::registerNative(jni::JNIEnv &env) {
+void JsonArray::registerNative(jni::JNIEnv& env) {
// Lookup the class
javaClass = *jni::Class<JsonArray>::Find(env).NewGlobalRef(env).release();
}
diff --git a/platform/android/src/gson/json_array.hpp b/platform/android/src/gson/json_array.hpp
index 8571ad5dba..c9ae98692f 100644
--- a/platform/android/src/gson/json_array.hpp
+++ b/platform/android/src/gson/json_array.hpp
@@ -13,6 +13,8 @@ class JsonArray : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/google/gson/JsonArray"; };
+ static jni::Object<JsonArray> New(jni::JNIEnv&, const std::vector<mapbox::geometry::value>&);
+
static std::vector<mapbox::geometry::value> convert(JNIEnv&, jni::Object<JsonArray>);
static jni::Class<JsonArray> javaClass;
diff --git a/platform/android/src/gson/json_element.cpp b/platform/android/src/gson/json_element.cpp
index 060b1e0fe2..5eaaf531f4 100644
--- a/platform/android/src/gson/json_element.cpp
+++ b/platform/android/src/gson/json_element.cpp
@@ -11,6 +11,34 @@ namespace mbgl {
namespace android {
namespace gson {
+/**
+ * Turn mapbox::geometry::value into Java Gson JsonElement
+ */
+class JsonElementEvaluator {
+public:
+
+ jni::JNIEnv& env;
+
+ jni::Object<JsonElement> operator()(const JsonPrimitive::value value) const {
+ return jni::Cast(env, JsonPrimitive::New(env, value), JsonElement::javaClass);
+ }
+
+ jni::Object<JsonElement> operator()(const std::vector<mapbox::geometry::value> &values) const {
+ return jni::Cast(env, JsonArray::New(env, values), JsonElement::javaClass);
+ }
+
+ jni::Object<JsonElement> operator()(const std::unordered_map<std::string, mapbox::geometry::value> &values) const {
+ return jni::Cast(env, JsonObject::New(env, values), JsonElement::javaClass);
+ }
+
+};
+
+
+jni::Object<JsonElement> JsonElement::New(jni::JNIEnv& env, const mapbox::geometry::value& value) {
+ JsonElementEvaluator evaluator { env } ;
+ return mapbox::geometry::value::visit(value, evaluator);
+}
+
mapbox::geometry::value JsonElement::convert(jni::JNIEnv &env, jni::Object<JsonElement> jsonElement) {
mapbox::geometry::value value;
diff --git a/platform/android/src/gson/json_element.hpp b/platform/android/src/gson/json_element.hpp
index 7619350617..d850caa526 100644
--- a/platform/android/src/gson/json_element.hpp
+++ b/platform/android/src/gson/json_element.hpp
@@ -13,6 +13,8 @@ class JsonElement : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/google/gson/JsonElement"; };
+ static jni::Object<JsonElement> New(jni::JNIEnv&, const mapbox::geometry::value&);
+
static mapbox::geometry::value convert(JNIEnv&, jni::Object<JsonElement>);
static bool isJsonObject(JNIEnv&, jni::Object<JsonElement>);
diff --git a/platform/android/src/gson/json_object.cpp b/platform/android/src/gson/json_object.cpp
index a704dae9dd..61b55f8b9e 100644
--- a/platform/android/src/gson/json_object.cpp
+++ b/platform/android/src/gson/json_object.cpp
@@ -9,6 +9,23 @@ namespace android {
namespace gson {
+jni::Object<JsonObject> JsonObject::New(jni::JNIEnv& env, const std::unordered_map<std::string, mapbox::geometry::value>& values) {
+ static auto constructor = JsonObject::javaClass.GetConstructor(env);
+ static auto addMethod = JsonObject::javaClass.GetMethod<void (jni::String, jni::Object<JsonElement>)>(env, "add");
+
+ jni::Object<JsonObject> jsonObject = JsonObject::javaClass.New(env, constructor);
+
+ for (auto &item : values) {
+ jni::Object<JsonElement> jsonElement = JsonElement::New(env, item.second);
+ jni::String key = jni::Make<jni::String>(env, item.first);
+ jsonObject.Call(env, addMethod, key, jsonElement);
+ jni::DeleteLocalRef(env, jsonElement);
+ jni::DeleteLocalRef(env, key);
+ }
+
+ return jsonObject;
+}
+
template <typename F> // void (jni::String, jni::Object<gson::JsonElement>)
static void iterateEntrySet(jni::JNIEnv& env, jni::Object<JsonObject> jsonObject, F callback) {
// Get Set<Map.Entry<String, JsonElement>>
diff --git a/platform/android/src/gson/json_object.hpp b/platform/android/src/gson/json_object.hpp
index aba8e40415..4bc61e51a2 100644
--- a/platform/android/src/gson/json_object.hpp
+++ b/platform/android/src/gson/json_object.hpp
@@ -13,6 +13,8 @@ class JsonObject : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/google/gson/JsonObject"; };
+ static jni::Object<JsonObject> New(jni::JNIEnv&, const std::unordered_map<std::string, mapbox::geometry::value>&);
+
static mapbox::geometry::property_map convert(JNIEnv&, jni::Object<JsonObject>);
static jni::Class<JsonObject> javaClass;
diff --git a/platform/android/src/gson/json_primitive.cpp b/platform/android/src/gson/json_primitive.cpp
index 58d0b45fe7..4e171c4845 100644
--- a/platform/android/src/gson/json_primitive.cpp
+++ b/platform/android/src/gson/json_primitive.cpp
@@ -1,9 +1,89 @@
#include "json_primitive.hpp"
+#include "../java/lang.hpp"
namespace mbgl {
namespace android {
namespace gson {
+/**
+ * Turn mapbox::geometry::value into Java Gson JsonPrimitives
+ */
+class JsonPrimitiveEvaluator {
+public:
+
+ jni::JNIEnv& env;
+
+ /**
+ * Create a null primitive
+ */
+ jni::Object<JsonPrimitive> operator()(const mapbox::geometry::null_value_t) const {
+ return jni::Object<JsonPrimitive>();
+ }
+
+ /**
+ * Create a primitive containing a string value
+ */
+ jni::Object<JsonPrimitive> operator()(const std::string value) const {
+ static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::String>(env);
+ auto jvalue = jni::Make<jni::String>(env, value);
+ auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, jvalue);
+ jni::DeleteLocalRef(env, jvalue);
+ return jsonPrimitive;
+ }
+
+ /**
+ * Create a primitive containing a number value with type double
+ */
+ jni::Object<JsonPrimitive> operator()(const double value) const {
+ static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::Object<java::lang::Number>>(env);
+ auto boxedValue = java::lang::Double::valueOf(env, value);
+ auto number = jni::Cast(env, boxedValue, java::lang::Number::javaClass);
+ auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, number);
+ jni::DeleteLocalRef(env, boxedValue);
+ return jsonPrimitive;
+ }
+
+ /**
+ * Create a primitive containing a number value with type long
+ */
+ jni::Object<JsonPrimitive> operator()(const int64_t value) const {
+ static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::Object<java::lang::Number>>(env);
+ auto boxedValue = java::lang::Long::valueOf(env, value);
+ auto number = jni::Cast(env, boxedValue, java::lang::Number::javaClass);
+ auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, number);
+ jni::DeleteLocalRef(env, boxedValue);
+ return jsonPrimitive;
+ }
+
+ /**
+ * Create a primitive containing a number value with type long
+ */
+ jni::Object<JsonPrimitive> operator()(const uint64_t value) const {
+ static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::Object<java::lang::Number>>(env);
+ auto boxedValue = java::lang::Long::valueOf(env, value);
+ auto number = jni::Cast(env, boxedValue, java::lang::Number::javaClass);
+ auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, number);
+ jni::DeleteLocalRef(env, boxedValue);
+ return jsonPrimitive;
+ }
+
+ /**
+ * Create a primitive containing a boolean value
+ */
+ jni::Object<JsonPrimitive> operator()(const bool value) const {
+ static auto constructor = JsonPrimitive::javaClass.GetConstructor<jni::Object<java::lang::Boolean>>(env);
+ auto boxedValue = java::lang::Boolean::valueOf(env, value);
+ auto jsonPrimitive = JsonPrimitive::javaClass.New(env, constructor, boxedValue);
+ jni::DeleteLocalRef(env, boxedValue);
+ return jsonPrimitive;
+ }
+};
+
+jni::Object<JsonPrimitive> JsonPrimitive::New(jni::JNIEnv &env, const value& value) {
+ JsonPrimitiveEvaluator evaluator { env };
+ return value::visit(value, evaluator);
+}
+
JsonPrimitive::value JsonPrimitive::convert(jni::JNIEnv &env, jni::Object<JsonPrimitive> jsonPrimitive) {
value value;
if (jsonPrimitive) {
diff --git a/platform/android/src/gson/json_primitive.hpp b/platform/android/src/gson/json_primitive.hpp
index 5fc8a2b485..c418e0ebe8 100644
--- a/platform/android/src/gson/json_primitive.hpp
+++ b/platform/android/src/gson/json_primitive.hpp
@@ -15,6 +15,8 @@ public:
static constexpr auto Name() { return "com/google/gson/JsonPrimitive"; };
+ static jni::Object<JsonPrimitive> New(jni::JNIEnv&, const value&);
+
static value convert(JNIEnv&, jni::Object<JsonPrimitive>);
static bool isBoolean(JNIEnv&, jni::Object<JsonPrimitive>);
diff --git a/platform/android/src/http_file_source.cpp b/platform/android/src/http_file_source.cpp
index 8eb9416e9d..cda84209ea 100644
--- a/platform/android/src/http_file_source.cpp
+++ b/platform/android/src/http_file_source.cpp
@@ -61,7 +61,7 @@ void RegisterNativeHTTPRequest(jni::JNIEnv& env) {
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
- jni::RegisterNativePeer<HTTPRequest>(env, HTTPRequest::javaClass, "mNativePtr",
+ jni::RegisterNativePeer<HTTPRequest>(env, HTTPRequest::javaClass, "nativePtr",
METHOD(&HTTPRequest::onFailure, "nativeOnFailure"),
METHOD(&HTTPRequest::onResponse, "nativeOnResponse"));
}
diff --git a/platform/android/src/image.cpp b/platform/android/src/image.cpp
index 2a33944b18..0456381578 100644
--- a/platform/android/src/image.cpp
+++ b/platform/android/src/image.cpp
@@ -16,7 +16,12 @@ PremultipliedImage decodeImage(const std::string& string) {
reinterpret_cast<const signed char*>(string.data()));
auto bitmap = android::BitmapFactory::DecodeByteArray(*env, array, 0, string.size());
- return android::Bitmap::GetImage(*env, bitmap);
+ jni::DeleteLocalRef(*env, array);
+
+ auto image = android::Bitmap::GetImage(*env, bitmap);
+ jni::DeleteLocalRef(*env, bitmap);
+
+ return image;
}
} // namespace mbgl
diff --git a/platform/android/src/java/lang.cpp b/platform/android/src/java/lang.cpp
new file mode 100644
index 0000000000..3c95737169
--- /dev/null
+++ b/platform/android/src/java/lang.cpp
@@ -0,0 +1,76 @@
+#include "lang.hpp"
+
+namespace mbgl {
+namespace android {
+namespace java {
+namespace lang {
+
+// Float
+
+jni::Object<Float> Float::valueOf(JNIEnv &env, jfloat value) {
+ static auto method = javaClass.GetStaticMethod<jni::Object<Float> (jni::jfloat)>(env, "valueOf");
+ return javaClass.Call(env, method, value);
+}
+
+void Float::registerNative(jni::JNIEnv &env) {
+ // Lookup the class
+ javaClass = *jni::Class<Float>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<Float> Float::javaClass;
+
+// Long
+
+jni::Object<Long> Long::valueOf(JNIEnv &env, jlong value) {
+ static auto method = javaClass.GetStaticMethod<jni::Object<Long> (jni::jlong)>(env, "valueOf");
+ return javaClass.Call(env, method, value);
+}
+
+void Long::registerNative(jni::JNIEnv &env) {
+ // Lookup the class
+ javaClass = *jni::Class<Long>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<Long> Long::javaClass;
+
+// Double
+
+jni::Object<Double> Double::valueOf(JNIEnv &env, jdouble value) {
+ static auto method = javaClass.GetStaticMethod<jni::Object<Double> (jni::jdouble)>(env, "valueOf");
+ return javaClass.Call(env, method, value);
+}
+
+void Double::registerNative(jni::JNIEnv &env) {
+ // Lookup the class
+ javaClass = *jni::Class<Double>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<Double> Double::javaClass;
+
+// Boolean
+
+jni::Object<Boolean> Boolean::valueOf(JNIEnv &env, jboolean value) {
+ static auto method = javaClass.GetStaticMethod<jni::Object<Boolean> (jni::jboolean)>(env, "valueOf");
+ return javaClass.Call(env, method, value);
+}
+
+void Boolean::registerNative(jni::JNIEnv &env) {
+ // Lookup the class
+ javaClass = *jni::Class<Boolean>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<Boolean> Boolean::javaClass;
+
+// Number
+
+void Number::registerNative(jni::JNIEnv &env) {
+ // Lookup the class
+ javaClass = *jni::Class<Number>::Find(env).NewGlobalRef(env).release();
+}
+
+jni::Class<Number> Number::javaClass;
+
+} // namespace lang
+} // namespace java
+} // namespace android
+} // namespace mbgl
diff --git a/platform/android/src/java/lang.hpp b/platform/android/src/java/lang.hpp
index dcf81a9d0c..981e3b14b7 100644
--- a/platform/android/src/java/lang.hpp
+++ b/platform/android/src/java/lang.hpp
@@ -1,18 +1,64 @@
#pragma once
+#include <jni/jni.hpp>
+#include <mbgl/util/noncopyable.hpp>
+
namespace mbgl {
namespace android {
namespace java {
namespace lang {
-class Float {
+class Float : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "java/lang/Float"; };
+
+ static jni::Object<Float> valueOf(JNIEnv&, jfloat);
+
+ static jni::Class<Float> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+};
+
+class Double : private mbgl::util::noncopyable {
+public:
+ static constexpr auto Name() { return "java/lang/Double"; };
+
+ static jni::Object<Double> valueOf(JNIEnv&, jdouble);
+
+ static jni::Class<Double> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+};
+
+class Long : private mbgl::util::noncopyable {
+public:
+ static constexpr auto Name() { return "java/lang/Long"; };
+
+ static jni::Object<Long> valueOf(JNIEnv&, jlong);
+
+ static jni::Class<Long> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
+};
+
+class Boolean : private mbgl::util::noncopyable {
+public:
+ static constexpr auto Name() { return "java/lang/Boolean"; };
+
+ static jni::Object<Boolean> valueOf(JNIEnv&, jboolean);
+
+ static jni::Class<Boolean> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
};
-class Number {
+class Number : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "java/lang/Number"; };
+
+ static jni::Class<Number> javaClass;
+
+ static void registerNative(jni::JNIEnv&);
};
} // namespace lang
diff --git a/platform/android/src/java/util.cpp b/platform/android/src/java/util.cpp
index effd2ae0d0..89c4c77794 100644
--- a/platform/android/src/java/util.cpp
+++ b/platform/android/src/java/util.cpp
@@ -5,12 +5,14 @@ namespace android {
namespace java {
namespace util {
+jni::Class<Arrays> Arrays::javaClass;
jni::Class<List> List::javaClass;
jni::Class<Set> Set::javaClass;
jni::Class<Map> Map::javaClass;
jni::Class<Map::Entry> Map::Entry::javaClass;
void registerNative(jni::JNIEnv& env) {
+ Arrays::javaClass = *jni::Class<Arrays>::Find(env).NewGlobalRef(env).release();
List::javaClass = *jni::Class<List>::Find(env).NewGlobalRef(env).release();
Set::javaClass = *jni::Class<Set>::Find(env).NewGlobalRef(env).release();
Map::javaClass = *jni::Class<Map>::Find(env).NewGlobalRef(env).release();
diff --git a/platform/android/src/java/util.hpp b/platform/android/src/java/util.hpp
index dedb8ac348..c6b07acac5 100644
--- a/platform/android/src/java/util.hpp
+++ b/platform/android/src/java/util.hpp
@@ -24,6 +24,21 @@ public:
};
+class Arrays : private mbgl::util::noncopyable {
+public:
+
+ static constexpr auto Name() { return "java/util/Arrays"; };
+
+ template <class T>
+ static jni::Object<List> asList(jni::JNIEnv& env, jni::Array<jni::Object<T>> array) {
+ static auto asList = Arrays::javaClass.GetStaticMethod<jni::Object<List>(jni::Array<jni::Object<>>)>(env, "asList");
+ return javaClass.Call(env, asList, (jni::Array<jni::Object<>>) array);
+ }
+
+ static jni::Class<Arrays> javaClass;
+
+};
+
class Set : private mbgl::util::noncopyable {
public:
diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp
index c2fd1c95ad..2f6ed96ab0 100755
--- a/platform/android/src/jni.cpp
+++ b/platform/android/src/jni.cpp
@@ -14,6 +14,7 @@
#include "geojson/feature.hpp"
#include "geojson/feature_collection.hpp"
#include "geojson/geometry.hpp"
+#include "geojson/geometry_collection.hpp"
#include "geojson/line_string.hpp"
#include "geojson/multi_line_string.hpp"
#include "geojson/multi_point.hpp"
@@ -40,17 +41,13 @@
#include "offline/offline_region_error.hpp"
#include "offline/offline_region_status.hpp"
#include "style/transition_options.hpp"
-#include "style/functions/categorical_stops.hpp"
-#include "style/functions/exponential_stops.hpp"
-#include "style/functions/identity_stops.hpp"
-#include "style/functions/interval_stops.hpp"
-#include "style/functions/stop.hpp"
#include "style/layers/layers.hpp"
#include "style/sources/source.hpp"
#include "style/light.hpp"
#include "snapshotter/map_snapshotter.hpp"
#include "snapshotter/map_snapshot.hpp"
#include "text/local_glyph_rasterizer_jni.hpp"
+#include "java/lang.hpp"
namespace mbgl {
namespace android {
@@ -116,11 +113,17 @@ void registerNatives(JavaVM *vm) {
java::util::registerNative(env);
PointF::registerNative(env);
RectF::registerNative(env);
+ java::lang::Number::registerNative(env);
+ java::lang::Float::registerNative(env);
+ java::lang::Boolean::registerNative(env);
+ java::lang::Double::registerNative(env);
+ java::lang::Long::registerNative(env);
// GeoJSON
geojson::Feature::registerNative(env);
geojson::FeatureCollection::registerNative(env);
geojson::Geometry::registerNative(env);
+ geojson::GeometryCollection::registerNative(env);
geojson::LineString::registerNative(env);
geojson::MultiLineString::registerNative(env);
geojson::MultiPoint::registerNative(env);
@@ -163,11 +166,6 @@ void registerNatives(JavaVM *vm) {
Source::registerNative(env);
Light::registerNative(env);
Position::registerNative(env);
- Stop::registerNative(env);
- CategoricalStops::registerNative(env);
- ExponentialStops::registerNative(env);
- IdentityStops::registerNative(env);
- IntervalStops::registerNative(env);
// Map
CameraPosition::registerNative(env);
diff --git a/platform/android/src/map/image.cpp b/platform/android/src/map/image.cpp
index 52e0e0d255..c3b22b0054 100644
--- a/platform/android/src/map/image.cpp
+++ b/platform/android/src/map/image.cpp
@@ -29,7 +29,7 @@ mbgl::style::Image Image::getImage(jni::JNIEnv& env, jni::Object<Image> image) {
}
jni::GetArrayRegion(env, *pixels, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get()));
-
+ jni::DeleteLocalRef(env, pixels);
return mbgl::style::Image {name, std::move(premultipliedImage), pixelRatio};
}
diff --git a/platform/android/src/map_renderer.cpp b/platform/android/src/map_renderer.cpp
index 2440ac93ef..f7e16b7091 100644
--- a/platform/android/src/map_renderer.cpp
+++ b/platform/android/src/map_renderer.cpp
@@ -136,7 +136,7 @@ void MapRenderer::render(JNIEnv&) {
renderer->render(*params);
// Deliver the snapshot if requested
- if (snapshotCallback) {
+ if (snapshotCallback && !paused) {
snapshotCallback->operator()(backend->readFramebuffer());
snapshotCallback.reset();
}
@@ -174,6 +174,14 @@ void MapRenderer::onSurfaceChanged(JNIEnv&, jint width, jint height) {
requestRender();
}
+void MapRenderer::onResume(JNIEnv&) {
+ paused = false;
+}
+
+void MapRenderer::onPause(JNIEnv&) {
+ paused = true;
+}
+
// Static methods //
jni::Class<MapRenderer> MapRenderer::javaClass;
@@ -192,7 +200,11 @@ void MapRenderer::registerNative(jni::JNIEnv& env) {
METHOD(&MapRenderer::onSurfaceCreated,
"nativeOnSurfaceCreated"),
METHOD(&MapRenderer::onSurfaceChanged,
- "nativeOnSurfaceChanged"));
+ "nativeOnSurfaceChanged"),
+ METHOD(&MapRenderer::onResume,
+ "nativeOnResume"),
+ METHOD(&MapRenderer::onPause,
+ "nativeOnPause"));
}
MapRenderer& MapRenderer::getNativePeer(JNIEnv& env, jni::Object<MapRenderer> jObject) {
diff --git a/platform/android/src/map_renderer.hpp b/platform/android/src/map_renderer.hpp
index c36357af7a..5fb5ef1a61 100644
--- a/platform/android/src/map_renderer.hpp
+++ b/platform/android/src/map_renderer.hpp
@@ -98,6 +98,10 @@ private:
void onSurfaceChanged(JNIEnv&, jint width, jint height);
+ void onResume(JNIEnv&);
+
+ void onPause(JNIEnv&);
+
private:
GenericUniqueWeakObject<MapRenderer> javaPeer;
@@ -120,6 +124,7 @@ private:
std::mutex updateMutex;
bool framebufferSizeChanged = false;
+ std::atomic<bool> paused {false};
std::unique_ptr<SnapshotCallback> snapshotCallback;
};
diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp
index 67fc132204..eecb76213b 100755
--- a/platform/android/src/native_map_view.cpp
+++ b/platform/android/src/native_map_view.cpp
@@ -288,13 +288,15 @@ void NativeMapView::setLatLng(jni::JNIEnv&, jni::jdouble latitude, jni::jdouble
map->setLatLng(mbgl::LatLng(latitude, longitude), insets, mbgl::AnimationOptions{mbgl::Milliseconds(duration)});
}
-jni::Object<CameraPosition> NativeMapView::getCameraForLatLngBounds(jni::JNIEnv& env, jni::Object<LatLngBounds> jBounds) {
- return CameraPosition::New(env, map->cameraForLatLngBounds(mbgl::android::LatLngBounds::getLatLngBounds(env, jBounds), insets));
+jni::Object<CameraPosition> NativeMapView::getCameraForLatLngBounds(jni::JNIEnv& env, jni::Object<LatLngBounds> jBounds, double top, double left, double bottom, double right) {
+ mbgl::EdgeInsets padding = {top, left, bottom, right};
+ return CameraPosition::New(env, map->cameraForLatLngBounds(mbgl::android::LatLngBounds::getLatLngBounds(env, jBounds), padding));
}
-jni::Object<CameraPosition> NativeMapView::getCameraForGeometry(jni::JNIEnv& env, jni::Object<geojson::Geometry> jGeometry, double bearing) {
+jni::Object<CameraPosition> NativeMapView::getCameraForGeometry(jni::JNIEnv& env, jni::Object<geojson::Geometry> jGeometry, double bearing, double top, double left, double bottom, double right) {
auto geometry = geojson::Geometry::convert(env, jGeometry);
- return CameraPosition::New(env, map->cameraForGeometry(geometry, insets, bearing));
+ mbgl::EdgeInsets padding = {top, left, bottom, right};
+ return CameraPosition::New(env, map->cameraForGeometry(geometry, padding, bearing));
}
void NativeMapView::setReachability(jni::JNIEnv&, jni::jboolean reachable) {
@@ -893,16 +895,9 @@ void NativeMapView::removeSource(JNIEnv& env, jni::Object<Source> obj, jlong sou
source->removeFromMap(env, obj, *map);
}
-void NativeMapView::addImage(JNIEnv& env, jni::String name, jni::jint w, jni::jint h, jni::jfloat scale, jni::Array<jbyte> pixels) {
- jni::NullCheck(env, &pixels);
- std::size_t size = pixels.Length(env);
-
- mbgl::PremultipliedImage premultipliedImage({ static_cast<uint32_t>(w), static_cast<uint32_t>(h) });
- if (premultipliedImage.bytes() != uint32_t(size)) {
- throw mbgl::util::SpriteImageException("Sprite image pixel count mismatch");
- }
-
- jni::GetArrayRegion(env, *pixels, 0, size, reinterpret_cast<jbyte*>(premultipliedImage.data.get()));
+void NativeMapView::addImage(JNIEnv& env, jni::String name, jni::Object<Bitmap> bitmap, jni::jfloat scale) {
+ jni::NullCheck(env, &bitmap);
+ mbgl::PremultipliedImage premultipliedImage = Bitmap::GetImage(env, bitmap);
map->getStyle().addImage(std::make_unique<mbgl::style::Image>(
jni::Make<std::string>(env, name),
diff --git a/platform/android/src/native_map_view.hpp b/platform/android/src/native_map_view.hpp
index 507d77ac5f..aff3b51c42 100755
--- a/platform/android/src/native_map_view.hpp
+++ b/platform/android/src/native_map_view.hpp
@@ -104,9 +104,9 @@ public:
void setLatLng(jni::JNIEnv&, jni::jdouble, jni::jdouble, jni::jlong);
- jni::Object<CameraPosition> getCameraForLatLngBounds(jni::JNIEnv&, jni::Object<mbgl::android::LatLngBounds>);
+ jni::Object<CameraPosition> getCameraForLatLngBounds(jni::JNIEnv&, jni::Object<mbgl::android::LatLngBounds>, double top, double left, double bottom, double right);
- jni::Object<CameraPosition> getCameraForGeometry(jni::JNIEnv&, jni::Object<geojson::Geometry>, double bearing);
+ jni::Object<CameraPosition> getCameraForGeometry(jni::JNIEnv&, jni::Object<geojson::Geometry>, double bearing, double top, double left, double bottom, double right);
void setReachability(jni::JNIEnv&, jni::jboolean);
@@ -236,7 +236,7 @@ public:
void removeSource(JNIEnv&, jni::Object<Source>, jlong nativePtr);
- void addImage(JNIEnv&, jni::String, jni::jint, jni::jint, jni::jfloat, jni::Array<jbyte>);
+ void addImage(JNIEnv&, jni::String, jni::Object<Bitmap> bitmap, jni::jfloat);
void addImages(JNIEnv&, jni::Array<jni::Object<mbgl::android::Image>>);
@@ -257,7 +257,6 @@ private:
MapRenderer& mapRenderer;
std::string styleUrl;
- std::string apiKey;
float pixelRatio;
diff --git a/platform/android/src/offline/offline_manager.cpp b/platform/android/src/offline/offline_manager.cpp
index 02871e7fdf..4960ae2845 100644
--- a/platform/android/src/offline/offline_manager.cpp
+++ b/platform/android/src/offline/offline_manager.cpp
@@ -102,7 +102,9 @@ void OfflineManager::ListOfflineRegionsCallback::onError(jni::JNIEnv& env,
std::exception_ptr error) {
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
std::string message = mbgl::util::toString(error);
- callback.Call(env, method, jni::Make<jni::String>(env, message));
+ auto jmessage = jni::Make<jni::String>(env, message);
+ callback.Call(env, method, jmessage);
+ jni::DeleteLocalRef(env, jmessage);
}
void OfflineManager::ListOfflineRegionsCallback::onList(jni::JNIEnv& env,
@@ -138,7 +140,9 @@ void OfflineManager::CreateOfflineRegionCallback::onError(jni::JNIEnv& env,
std::exception_ptr error) {
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
std::string message = mbgl::util::toString(error);
- callback.Call(env, method, jni::Make<jni::String>(env, message));
+ auto jmessage = jni::Make<jni::String>(env, message);
+ callback.Call(env, method, jmessage);
+ jni::DeleteLocalRef(env, jmessage);
}
void OfflineManager::CreateOfflineRegionCallback::onCreate(jni::JNIEnv& env,
diff --git a/platform/android/src/offline/offline_region.cpp b/platform/android/src/offline/offline_region.cpp
index 856434d266..27de76fb00 100644
--- a/platform/android/src/offline/offline_region.cpp
+++ b/platform/android/src/offline/offline_region.cpp
@@ -239,7 +239,9 @@ void OfflineRegion::OfflineRegionStatusCallback::onError(jni::JNIEnv& env,
std::exception_ptr error) {
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
std::string message = mbgl::util::toString(error);
- callback.Call(env, method, jni::Make<jni::String>(env, message));
+ auto jmessage = jni::Make<jni::String>(env, message);
+ callback.Call(env, method, jmessage);
+ jni::DeleteLocalRef(env, jmessage);
}
void OfflineRegion::OfflineRegionStatusCallback::onStatus(jni::JNIEnv& env,
@@ -267,7 +269,9 @@ void OfflineRegion::OfflineRegionDeleteCallback::onError(jni::JNIEnv& env,
std::exception_ptr error) {
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
std::string message = mbgl::util::toString(error);
- callback.Call(env, method, jni::Make<jni::String>(env, message));
+ auto jmessage = jni::Make<jni::String>(env, message);
+ callback.Call(env, method, jmessage);
+ jni::DeleteLocalRef(env, jmessage);
}
void OfflineRegion::OfflineRegionDeleteCallback::onDelete(jni::JNIEnv& env, jni::Object<OfflineRegion::OfflineRegionDeleteCallback> callback) {
@@ -289,7 +293,9 @@ void OfflineRegion::OfflineRegionUpdateMetadataCallback::onError(jni::JNIEnv& en
std::exception_ptr error) {
static auto method = javaClass.GetMethod<void (jni::String)>(env, "onError");
std::string message = mbgl::util::toString(error);
- callback.Call(env, method, jni::Make<jni::String>(env, message));
+ auto jmessage = jni::Make<jni::String>(env, message);
+ callback.Call(env, method, jmessage);
+ jni::DeleteLocalRef(env, jmessage);
}
void OfflineRegion::OfflineRegionUpdateMetadataCallback::onUpdate(jni::JNIEnv& env,
diff --git a/platform/android/src/snapshotter/map_snapshotter.cpp b/platform/android/src/snapshotter/map_snapshotter.cpp
index 71f8b4f4c0..a006953d36 100644
--- a/platform/android/src/snapshotter/map_snapshotter.cpp
+++ b/platform/android/src/snapshotter/map_snapshotter.cpp
@@ -71,7 +71,9 @@ void MapSnapshotter::start(JNIEnv& env) {
if (err) {
// error handler callback
static auto onSnapshotFailed = javaClass.GetMethod<void (jni::String)>(*_env, "onSnapshotFailed");
- javaPeer->Call(*_env, onSnapshotFailed, jni::Make<jni::String>(*_env, util::toString(err)));
+ auto message = jni::Make<jni::String>(*_env, util::toString(err));
+ javaPeer->Call(*_env, onSnapshotFailed, message);
+ jni::DeleteLocalRef(*_env, message);
} else {
// Create the wrapper
auto mapSnapshot = android::MapSnapshot::New(*_env, std::move(image), pixelRatio, attributions, showLogo, pointForFn);
diff --git a/platform/android/src/style/conversion/function.hpp b/platform/android/src/style/conversion/function.hpp
index ad01a7afc2..d6669b4508 100644
--- a/platform/android/src/style/conversion/function.hpp
+++ b/platform/android/src/style/conversion/function.hpp
@@ -5,13 +5,9 @@
#include "../../conversion/constant.hpp"
#include "types.hpp"
#include "../../java/lang.hpp"
-#include "../functions/stop.hpp"
-#include "../functions/categorical_stops.hpp"
-#include "../functions/exponential_stops.hpp"
-#include "../functions/identity_stops.hpp"
-#include "../functions/interval_stops.hpp"
#include <jni/jni.hpp>
+#include "../../gson/json_element.hpp"
#include <tuple>
#include <map>
@@ -20,205 +16,33 @@ namespace mbgl {
namespace android {
namespace conversion {
-/**
- * Conversion from core composite value to java type
- */
-class CategoricalValueEvaluator {
-public:
-
- CategoricalValueEvaluator(jni::JNIEnv& _env) : env(_env) {}
-
- template <class T>
- jni::jobject* operator()(const T &value) const {
- return *convert<jni::jobject*, T>(env, value);
- }
-
-private:
- jni::JNIEnv& env;
-};
-
-/**
- * Conversion from core composite value to java type
- */
-template <>
-struct Converter<jni::jobject*, mbgl::style::CategoricalValue> {
-
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::CategoricalValue& value) const {
- CategoricalValueEvaluator evaluator(env);
- return apply_visitor(evaluator, value);
- }
-};
-
-template <class I, class O>
-jni::Array<jni::Object<Stop>> toFunctionStopJavaArray(jni::JNIEnv& env, std::map<I, O> value) {
-
- auto jarray = jni::Array<jni::Object<Stop>>::New(env, value.size(), Stop::javaClass);
-
- size_t i = 0;
- for (auto const& stop : value) {
- jni::jobject* in = *convert<jni::jobject*, I>(env, stop.first);
- jni::jobject* out = *convert<jni::jobject*, O>(env, stop.second);
-
- auto jstop = Stop::New(env, jni::Object<>(in), jni::Object<>(out));
- jarray.Set(env, i, jstop);
-
- jni::DeleteLocalRef(env, in);
- jni::DeleteLocalRef(env, out);
- jni::DeleteLocalRef(env, jstop);
-
- i++;
- }
-
- return jarray;
-}
-
-template <class I, class O>
-jni::Array<jni::Object<Stop>> toFunctionStopJavaArray(jni::JNIEnv& env, std::map<float, std::map<I, O>> value) {
-
- auto jarray = jni::Array<jni::Object<Stop>>::New(env, value.size(), Stop::javaClass);
-
- for (auto const& zoomLevelMap : value) {
- size_t i = 0;
- for (auto const& stop: zoomLevelMap.second) {
- auto zoom = jni::Object<java::lang::Number>(*convert<jni::jobject*>(env, zoomLevelMap.first));
- auto in = jni::Object<>(*convert<jni::jobject*, I>(env, stop.first));
- auto out = jni::Object<>(*convert<jni::jobject*, O>(env, stop.second));
- auto compositeValue = Stop::CompositeValue::New(env, zoom, in);
-
- auto jstop = Stop::New(env, compositeValue, out);
- jarray.Set(env, i, jstop);
-
- jni::DeleteLocalRef(env, zoom);
- jni::DeleteLocalRef(env, in);
- jni::DeleteLocalRef(env, out);
- jni::DeleteLocalRef(env, compositeValue);
- jni::DeleteLocalRef(env, jstop);
-
- i++;
- }
- }
-
- return jarray;
-}
-
-template <class I, typename O>
-inline jni::jobject* convertCompositeStopsArray(jni::JNIEnv& env, std::map<float, std::map<I, O>> value) {
- static jni::jclass* javaClass = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/mapboxsdk/style/functions/stops/Stop")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *javaClass, "<init>", "(Ljava/lang/Object;Ljava/lang/Object;)V");
-
- jni::jarray<jni::jobject>& jarray = jni::NewObjectArray(env, value.size(), *javaClass);
-
- size_t i = 0;
- for (auto const& stop : value) {
- jni::jobject* in = *convert<jni::jobject*, I>(env, stop.first);
- jni::jobject* out = *convert<jni::jobject*, O>(env, stop.second);
- jni::SetObjectArrayElement(env, jarray, i, &jni::NewObject(env, *javaClass, *constructor, in, out));
- i++;
- jni::DeleteLocalRef(env, in);
- jni::DeleteLocalRef(env, out);
- }
-
- return &jarray;
-}
-
-/**
- * Conversion from core function stops to Stops java subclasses
- */
template <class T>
-class StopsEvaluator {
-public:
-
- StopsEvaluator(jni::JNIEnv& _env) : env(_env) {}
-
- jni::jobject* operator()(const mbgl::style::CategoricalStops<T> &value) const {
- return CategoricalStops::New(env, toFunctionStopJavaArray(env, value.stops)).Get();
- }
-
- jni::jobject* operator()(const mbgl::style::CompositeCategoricalStops<T> &value) const {
- return CategoricalStops::New(env, toFunctionStopJavaArray(env, value.stops)).Get();
- }
-
- jni::jobject* operator()(const mbgl::style::ExponentialStops<T> &value) const {
- return ExponentialStops::New(env, jni::Object<java::lang::Float>(*convert<jni::jobject*>(env, value.base)), toFunctionStopJavaArray(env, value.stops)).Get();
- }
+struct Converter<jni::Object<android::gson::JsonElement>, mbgl::style::CameraFunction<T>> {
- jni::jobject* operator()(const mbgl::style::CompositeExponentialStops<T> &value) const {
- return ExponentialStops::New(env, jni::Object<java::lang::Float>(*convert<jni::jobject*>(env, value.base)), toFunctionStopJavaArray(env, value.stops)).Get();
+ Result<jni::Object<android::gson::JsonElement>> operator()(jni::JNIEnv& env, const mbgl::style::CameraFunction<T>& value) const {
+ // Convert expressions
+ mbgl::Value expressionValue = value.getExpression().serialize();
+ return gson::JsonElement::New(env, expressionValue);
}
-
- jni::jobject* operator()(const mbgl::style::IdentityStops<T> &) const {
- return IdentityStops::New(env).Get();
- }
-
- jni::jobject* operator()(const mbgl::style::IntervalStops<T> &value) const {
- return IntervalStops::New(env, toFunctionStopJavaArray(env, value.stops)).Get();
- }
-
- jni::jobject* operator()(const mbgl::style::CompositeIntervalStops<T> &value) const {
- return IntervalStops::New(env, toFunctionStopJavaArray(env, value.stops)).Get();
- }
-
-private:
- jni::JNIEnv& env;
};
template <class T>
-struct Converter<jni::jobject*, mbgl::style::CameraFunction<T>> {
+struct Converter<jni::Object<android::gson::JsonElement>, mbgl::style::SourceFunction<T>> {
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::CameraFunction<T>& value) const {
- static jni::jclass* clazz = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/mapboxsdk/style/functions/CameraFunction")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *clazz, "<init>", "(Lcom/mapbox/mapboxsdk/style/functions/stops/Stops;)V");
-
- StopsEvaluator<T> evaluator(env);
- jni::jobject* stops = apply_visitor(evaluator, value.stops);
- jni::jobject* converted = &jni::NewObject(env, *clazz, *constructor, stops);
-
- return { converted };
- }
-};
-
-template <class T>
-struct Converter<jni::jobject*, mbgl::style::SourceFunction<T>> {
-
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::SourceFunction<T>& value) const {
- static jni::jclass* clazz = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/mapboxsdk/style/functions/SourceFunction")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *clazz, "<init>",
- "(Ljava/lang/Object;Ljava/lang/String;Lcom/mapbox/mapboxsdk/style/functions/stops/Stops;)V");
-
- // Convert stops
- StopsEvaluator<T> evaluator(env);
- jni::jobject* stops = apply_visitor(evaluator, value.stops);
-
- // Convert default value
- jni::jobject* defaultValue = nullptr;
- if (value.defaultValue) {
- defaultValue = *convert<jni::jobject*>(env, *value.defaultValue);
- }
-
- return { &jni::NewObject(env, *clazz, *constructor, defaultValue, jni::Make<jni::String>(env, value.property).Get(), stops) };
+ Result<jni::Object<android::gson::JsonElement>> operator()(jni::JNIEnv& env, const mbgl::style::SourceFunction<T>& value) const {
+ // Convert expressions
+ mbgl::Value expressionValue = value.getExpression().serialize();
+ return gson::JsonElement::New(env, expressionValue);
}
};
template <class T>
-struct Converter<jni::jobject*, mbgl::style::CompositeFunction<T>> {
-
- Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::CompositeFunction<T>& value) const {
- static jni::jclass* clazz = jni::NewGlobalRef(env, &jni::FindClass(env, "com/mapbox/mapboxsdk/style/functions/CompositeFunction")).release();
- static jni::jmethodID* constructor = &jni::GetMethodID(env, *clazz, "<init>",
- "(Ljava/lang/Object;Ljava/lang/String;Lcom/mapbox/mapboxsdk/style/functions/stops/Stops;)V");
-
- // Convert stops
- StopsEvaluator<T> evaluator(env);
- jni::jobject* stops = apply_visitor(evaluator, value.stops);
-
-
- // Convert default value
- jni::jobject* defaultValue = nullptr;
- if (value.defaultValue) {
- defaultValue = *convert<jni::jobject*>(env, *value.defaultValue);
- }
+struct Converter<jni::Object<android::gson::JsonElement>, mbgl::style::CompositeFunction<T>> {
- return { &jni::NewObject(env, *clazz, *constructor, defaultValue, jni::Make<jni::String>(env, value.property).Get(), stops) };
+ Result<jni::Object<android::gson::JsonElement>> operator()(jni::JNIEnv& env, const mbgl::style::CompositeFunction<T>& value) const {
+ // Convert expressions
+ mbgl::Value expressionValue = value.getExpression().serialize();
+ return gson::JsonElement::New(env, expressionValue);
}
};
diff --git a/platform/android/src/style/conversion/property_value.hpp b/platform/android/src/style/conversion/property_value.hpp
index a58cf975a7..902d1e80b2 100644
--- a/platform/android/src/style/conversion/property_value.hpp
+++ b/platform/android/src/style/conversion/property_value.hpp
@@ -2,6 +2,7 @@
#include <mbgl/style/property_value.hpp>
#include <mbgl/style/data_driven_property_value.hpp>
+#include <mbgl/style/heatmap_color_property_value.hpp>
#include "../../conversion/conversion.hpp"
#include "../../conversion/constant.hpp"
#include "types.hpp"
@@ -30,15 +31,15 @@ public:
}
jni::jobject* operator()(const mbgl::style::CameraFunction<T> &value) const {
- return *convert<jni::jobject*, mbgl::style::CameraFunction<T>>(env, value);
+ return *convert<jni::Object<android::gson::JsonElement>, mbgl::style::CameraFunction<T>>(env, value);
}
jni::jobject* operator()(const mbgl::style::SourceFunction<T> &value) const {
- return *convert<jni::jobject*, mbgl::style::SourceFunction<T>>(env, value);
+ return *convert<jni::Object<android::gson::JsonElement>, mbgl::style::SourceFunction<T>>(env, value);
}
jni::jobject* operator()(const mbgl::style::CompositeFunction<T> &value) const {
- return *convert<jni::jobject*, mbgl::style::CompositeFunction<T>>(env, value);
+ return *convert<jni::Object<android::gson::JsonElement>, mbgl::style::CompositeFunction<T>>(env, value);
}
private:
@@ -70,6 +71,18 @@ struct Converter<jni::jobject*, mbgl::style::DataDrivenPropertyValue<T>> {
}
};
+/**
+ * Convert core heat map color property value to java
+ */
+template <>
+struct Converter<jni::jobject*, mbgl::style::HeatmapColorPropertyValue> {
+
+ Result<jni::jobject*> operator()(jni::JNIEnv& env, const mbgl::style::HeatmapColorPropertyValue value) const {
+ PropertyValueEvaluator<mbgl::style::HeatmapColorPropertyValue> evaluator(env);
+ return *convert<jni::jobject*>(env, value.evaluate(evaluator));
+ }
+};
+
} // namespace conversion
} // namespace android
} // namespace mbgl
diff --git a/platform/android/src/style/functions/categorical_stops.cpp b/platform/android/src/style/functions/categorical_stops.cpp
deleted file mode 100644
index 2aff9730a7..0000000000
--- a/platform/android/src/style/functions/categorical_stops.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "categorical_stops.hpp"
-
-namespace mbgl {
-namespace android {
-
-jni::Object<CategoricalStops> CategoricalStops::New(jni::JNIEnv& env, jni::Array<jni::Object<Stop>> stops) {
- static auto constructor = CategoricalStops::javaClass.GetConstructor<jni::Array<jni::Object<Stop>>>(env);
- return CategoricalStops::javaClass.New(env, constructor, stops);
-}
-
-jni::Class<CategoricalStops> CategoricalStops::javaClass;
-
-void CategoricalStops::registerNative(jni::JNIEnv& env) {
- CategoricalStops::javaClass = *jni::Class<CategoricalStops>::Find(env).NewGlobalRef(env).release();
-}
-
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/functions/categorical_stops.hpp b/platform/android/src/style/functions/categorical_stops.hpp
deleted file mode 100644
index a198c8d5c9..0000000000
--- a/platform/android/src/style/functions/categorical_stops.hpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-
-#include <mbgl/util/noncopyable.hpp>
-#include <jni/jni.hpp>
-
-#include "stop.hpp"
-
-namespace mbgl {
-namespace android {
-
-class CategoricalStops : private mbgl::util::noncopyable {
-public:
- static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/functions/stops/CategoricalStops"; };
-
- static jni::Object<CategoricalStops> New(jni::JNIEnv&, jni::Array<jni::Object<Stop>>);
-
- static jni::Class<CategoricalStops> javaClass;
-
- static void registerNative(jni::JNIEnv&);
-};
-
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/functions/exponential_stops.cpp b/platform/android/src/style/functions/exponential_stops.cpp
deleted file mode 100644
index 6390a0ec35..0000000000
--- a/platform/android/src/style/functions/exponential_stops.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "exponential_stops.hpp"
-
-namespace mbgl {
-namespace android {
-
-jni::Object<ExponentialStops> ExponentialStops::New(jni::JNIEnv& env, jni::Object<java::lang::Float> base, jni::Array<jni::Object<Stop>> stops) {
- static auto constructor = ExponentialStops::javaClass.GetConstructor<jni::Object<java::lang::Float>, jni::Array<jni::Object<Stop>>>(env);
- return ExponentialStops::javaClass.New(env, constructor, base, stops);
-}
-
-jni::Class<ExponentialStops> ExponentialStops::javaClass;
-
-void ExponentialStops::registerNative(jni::JNIEnv& env) {
- ExponentialStops::javaClass = *jni::Class<ExponentialStops>::Find(env).NewGlobalRef(env).release();
-}
-
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/functions/exponential_stops.hpp b/platform/android/src/style/functions/exponential_stops.hpp
deleted file mode 100644
index 391d723cef..0000000000
--- a/platform/android/src/style/functions/exponential_stops.hpp
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-#include <mbgl/util/noncopyable.hpp>
-#include <jni/jni.hpp>
-
-#include "../../java/lang.hpp"
-#include "stop.hpp"
-
-namespace mbgl {
-namespace android {
-
-class ExponentialStops : private mbgl::util::noncopyable {
-public:
- static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/functions/stops/ExponentialStops"; };
-
- static jni::Object<ExponentialStops> New(jni::JNIEnv&, jni::Object<java::lang::Float>, jni::Array<jni::Object<Stop>>);
-
- static jni::Class<ExponentialStops> javaClass;
-
- static void registerNative(jni::JNIEnv&);
-};
-
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/functions/identity_stops.cpp b/platform/android/src/style/functions/identity_stops.cpp
deleted file mode 100644
index 239b0ddb88..0000000000
--- a/platform/android/src/style/functions/identity_stops.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "identity_stops.hpp"
-
-namespace mbgl {
-namespace android {
-
-jni::Object<IdentityStops> IdentityStops::New(jni::JNIEnv& env) {
- static auto constructor = IdentityStops::javaClass.GetConstructor<>(env);
- return IdentityStops::javaClass.New(env, constructor);
-}
-
-jni::Class<IdentityStops> IdentityStops::javaClass;
-
-void IdentityStops::registerNative(jni::JNIEnv& env) {
- IdentityStops::javaClass = *jni::Class<IdentityStops>::Find(env).NewGlobalRef(env).release();
-}
-
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/functions/identity_stops.hpp b/platform/android/src/style/functions/identity_stops.hpp
deleted file mode 100644
index 150b2135f0..0000000000
--- a/platform/android/src/style/functions/identity_stops.hpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#pragma once
-
-#include <mbgl/util/noncopyable.hpp>
-#include <jni/jni.hpp>
-
-namespace mbgl {
-namespace android {
-
-class IdentityStops : private mbgl::util::noncopyable {
-public:
- static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/functions/stops/IdentityStops"; };
-
- static jni::Object<IdentityStops> New(jni::JNIEnv&);
-
- static jni::Class<IdentityStops> javaClass;
-
- static void registerNative(jni::JNIEnv&);
-};
-
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/functions/interval_stops.cpp b/platform/android/src/style/functions/interval_stops.cpp
deleted file mode 100644
index c3d9b6513f..0000000000
--- a/platform/android/src/style/functions/interval_stops.cpp
+++ /dev/null
@@ -1,18 +0,0 @@
-#include "interval_stops.hpp"
-
-namespace mbgl {
-namespace android {
-
-jni::Object<IntervalStops> IntervalStops::New(jni::JNIEnv& env, jni::Array<jni::Object<Stop>> stops) {
- static auto constructor = IntervalStops::javaClass.GetConstructor<jni::Array<jni::Object<Stop>>>(env);
- return IntervalStops::javaClass.New(env, constructor, stops);
-}
-
-jni::Class<IntervalStops> IntervalStops::javaClass;
-
-void IntervalStops::registerNative(jni::JNIEnv& env) {
- IntervalStops::javaClass = *jni::Class<IntervalStops>::Find(env).NewGlobalRef(env).release();
-}
-
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/functions/interval_stops.hpp b/platform/android/src/style/functions/interval_stops.hpp
deleted file mode 100644
index e3f75159cf..0000000000
--- a/platform/android/src/style/functions/interval_stops.hpp
+++ /dev/null
@@ -1,23 +0,0 @@
-#pragma once
-
-#include <mbgl/util/noncopyable.hpp>
-#include <jni/jni.hpp>
-
-#include "stop.hpp"
-
-namespace mbgl {
-namespace android {
-
-class IntervalStops : private mbgl::util::noncopyable {
-public:
- static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/functions/stops/IntervalStops"; };
-
- static jni::Object<IntervalStops> New(jni::JNIEnv&, jni::Array<jni::Object<Stop>>);
-
- static jni::Class<IntervalStops> javaClass;
-
- static void registerNative(jni::JNIEnv&);
-};
-
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/functions/stop.cpp b/platform/android/src/style/functions/stop.cpp
deleted file mode 100644
index f9ed4b7368..0000000000
--- a/platform/android/src/style/functions/stop.cpp
+++ /dev/null
@@ -1,21 +0,0 @@
-#include "interval_stops.hpp"
-
-namespace mbgl {
-namespace android {
-
-jni::Object<Stop::CompositeValue> Stop::CompositeValue::New(jni::JNIEnv& env, jni::Object<java::lang::Number> zoom, jni::Object<> value) {
- static auto constructor = Stop::CompositeValue::javaClass.GetConstructor<jni::Object<java::lang::Number>, jni::Object<>>(env);
- return Stop::CompositeValue::javaClass.New(env, constructor, zoom, value);
-}
-
-jni::Class<Stop> Stop::javaClass;
-
-jni::Class<Stop::CompositeValue> Stop::CompositeValue::javaClass;
-
-void Stop::registerNative(jni::JNIEnv& env) {
- Stop::javaClass = *jni::Class<Stop>::Find(env).NewGlobalRef(env).release();
- Stop::CompositeValue::javaClass = *jni::Class<Stop::CompositeValue>::Find(env).NewGlobalRef(env).release();
-}
-
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/functions/stop.hpp b/platform/android/src/style/functions/stop.hpp
deleted file mode 100644
index 7c697db65d..0000000000
--- a/platform/android/src/style/functions/stop.hpp
+++ /dev/null
@@ -1,36 +0,0 @@
-#pragma once
-
-#include <mbgl/util/noncopyable.hpp>
-#include <jni/jni.hpp>
-
-#include "../../java/lang.hpp"
-
-namespace mbgl {
-namespace android {
-
-class Stop : private mbgl::util::noncopyable {
-public:
- static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/functions/stops/Stop"; };
-
- template<class I, class O>
- static jni::Object<Stop> New(jni::JNIEnv& env, jni::Object<I> in, jni::Object<O> out) {
- static auto constructor = Stop::javaClass.GetConstructor<jni::Object<>, jni::Object<>>(env);
- return Stop::javaClass.New(env, constructor, (jni::Object<>) in, (jni::Object<>) out);
- }
-
- static jni::Class<Stop> javaClass;
-
- static void registerNative(jni::JNIEnv&);
-
- class CompositeValue : private mbgl::util::noncopyable {
- public:
- static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/functions/stops/Stop$CompositeValue"; };
-
- static jni::Object<Stop::CompositeValue> New(jni::JNIEnv&, jni::Object<java::lang::Number>, jni::Object<>);
-
- static jni::Class<Stop::CompositeValue> javaClass;
- };
-};
-
-} // namespace android
-} // namespace mbgl
diff --git a/platform/android/src/style/layers/custom_layer.cpp b/platform/android/src/style/layers/custom_layer.cpp
index 51a48520bf..61e74a9cf5 100644
--- a/platform/android/src/style/layers/custom_layer.cpp
+++ b/platform/android/src/style/layers/custom_layer.cpp
@@ -7,14 +7,10 @@
namespace mbgl {
namespace android {
- CustomLayer::CustomLayer(jni::JNIEnv& env, jni::String layerId, jni::jlong initializeFunction, jni::jlong renderFunction, jni::jlong contextLostFunction, jni::jlong deinitializeFunction, jni::jlong context)
+ CustomLayer::CustomLayer(jni::JNIEnv& env, jni::String layerId, jni::jlong host)
: Layer(env, std::make_unique<mbgl::style::CustomLayer>(
jni::Make<std::string>(env, layerId),
- reinterpret_cast<mbgl::style::CustomLayerInitializeFunction>(initializeFunction),
- reinterpret_cast<mbgl::style::CustomLayerRenderFunction>(renderFunction),
- reinterpret_cast<mbgl::style::CustomLayerContextLostFunction>(contextLostFunction),
- reinterpret_cast<mbgl::style::CustomLayerDeinitializeFunction>(deinitializeFunction),
- reinterpret_cast<void*>(context))
+ std::unique_ptr<mbgl::style::CustomLayerHost>(reinterpret_cast<mbgl::style::CustomLayerHost*>(host)))
) {
}
@@ -53,7 +49,7 @@ namespace android {
// Register the peer
jni::RegisterNativePeer<CustomLayer>(
env, CustomLayer::javaClass, "nativePtr",
- std::make_unique<CustomLayer, JNIEnv&, jni::String, jni::jlong, jni::jlong, jni::jlong, jni::jlong, jni::jlong>,
+ std::make_unique<CustomLayer, JNIEnv&, jni::String, jni::jlong>,
"initialize",
"finalize",
METHOD(&CustomLayer::update, "nativeUpdate"));
diff --git a/platform/android/src/style/layers/custom_layer.hpp b/platform/android/src/style/layers/custom_layer.hpp
index 9e079c1288..7eb649d923 100644
--- a/platform/android/src/style/layers/custom_layer.hpp
+++ b/platform/android/src/style/layers/custom_layer.hpp
@@ -16,7 +16,7 @@ public:
static void registerNative(jni::JNIEnv&);
- CustomLayer(jni::JNIEnv&, jni::String, jni::jlong, jni::jlong, jni::jlong, jni::jlong, jni::jlong);
+ CustomLayer(jni::JNIEnv&, jni::String, jni::jlong);
CustomLayer(mbgl::Map&, mbgl::style::CustomLayer&);
diff --git a/platform/android/src/style/layers/heatmap_layer.cpp b/platform/android/src/style/layers/heatmap_layer.cpp
index 609499ec93..b3d90faab7 100644
--- a/platform/android/src/style/layers/heatmap_layer.cpp
+++ b/platform/android/src/style/layers/heatmap_layer.cpp
@@ -79,6 +79,16 @@ namespace android {
layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::setHeatmapIntensityTransition(options);
}
+ jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapColor(jni::JNIEnv& env) {
+ using namespace mbgl::android::conversion;
+ auto propertyValue = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapColor();
+ if (propertyValue.isUndefined()) {
+ propertyValue = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getDefaultHeatmapColor();
+ }
+ Result<jni::jobject*> converted = convert<jni::jobject*>(env, propertyValue);
+ return jni::Object<jni::ObjectTag>(*converted);
+ }
+
jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapOpacity(jni::JNIEnv& env) {
using namespace mbgl::android::conversion;
Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapOpacity());
@@ -125,6 +135,7 @@ namespace android {
METHOD(&HeatmapLayer::getHeatmapIntensityTransition, "nativeGetHeatmapIntensityTransition"),
METHOD(&HeatmapLayer::setHeatmapIntensityTransition, "nativeSetHeatmapIntensityTransition"),
METHOD(&HeatmapLayer::getHeatmapIntensity, "nativeGetHeatmapIntensity"),
+ METHOD(&HeatmapLayer::getHeatmapColor, "nativeGetHeatmapColor"),
METHOD(&HeatmapLayer::getHeatmapOpacityTransition, "nativeGetHeatmapOpacityTransition"),
METHOD(&HeatmapLayer::setHeatmapOpacityTransition, "nativeSetHeatmapOpacityTransition"),
METHOD(&HeatmapLayer::getHeatmapOpacity, "nativeGetHeatmapOpacity"));
diff --git a/platform/android/src/style/layers/heatmap_layer.hpp b/platform/android/src/style/layers/heatmap_layer.hpp
index 85f9f0292e..9e8908b062 100644
--- a/platform/android/src/style/layers/heatmap_layer.hpp
+++ b/platform/android/src/style/layers/heatmap_layer.hpp
@@ -39,6 +39,8 @@ public:
void setHeatmapIntensityTransition(jni::JNIEnv&, jlong duration, jlong delay);
jni::Object<TransitionOptions> getHeatmapIntensityTransition(jni::JNIEnv&);
+ jni::Object<jni::ObjectTag> getHeatmapColor(jni::JNIEnv&);
+
jni::Object<jni::ObjectTag> getHeatmapOpacity(jni::JNIEnv&);
void setHeatmapOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay);
jni::Object<TransitionOptions> getHeatmapOpacityTransition(jni::JNIEnv&);
diff --git a/platform/android/src/style/layers/layer.cpp b/platform/android/src/style/layers/layer.cpp
index 29530879a5..6fe6e3cb29 100644
--- a/platform/android/src/style/layers/layer.cpp
+++ b/platform/android/src/style/layers/layer.cpp
@@ -25,6 +25,7 @@
// C++ -> Java conversion
#include "../conversion/property_value.hpp"
+#include <mbgl/style/filter.hpp>
#include <string>
@@ -134,6 +135,38 @@ namespace android {
layer.accept(SetFilterEvaluator {std::move(*converted)});
}
+ struct GetFilterEvaluator {
+ mbgl::style::Filter noop(std::string layerType) {
+ Log::Warning(mbgl::Event::JNI, "%s doesn't support filter", layerType.c_str());
+ return {};
+ }
+
+ mbgl::style::Filter operator()(style::BackgroundLayer&) { return noop("BackgroundLayer"); }
+ mbgl::style::Filter operator()(style::CustomLayer&) { return noop("CustomLayer"); }
+ mbgl::style::Filter operator()(style::RasterLayer&) { return noop("RasterLayer"); }
+ mbgl::style::Filter operator()(style::HillshadeLayer&) { return noop("HillshadeLayer"); }
+
+ template <class LayerType>
+ mbgl::style::Filter operator()(LayerType& layer) {
+ return layer.getFilter();
+ }
+ };
+
+ jni::Object<gson::JsonElement> Layer::getFilter(jni::JNIEnv& env) {
+ using namespace mbgl::style;
+ using namespace mbgl::style::conversion;
+
+ Filter filter = layer.accept(GetFilterEvaluator());
+
+ jni::Object<gson::JsonElement> converted;
+ if (filter.is<ExpressionFilter>()) {
+ ExpressionFilter filterExpression = filter.get<ExpressionFilter>();
+ mbgl::Value expressionValue = filterExpression.expression.get()->serialize();
+ converted = gson::JsonElement::New(env, expressionValue);
+ }
+ return converted;
+ }
+
struct SetSourceLayerEvaluator {
std::string sourceLayer;
@@ -208,6 +241,7 @@ namespace android {
METHOD(&Layer::setLayoutProperty, "nativeSetLayoutProperty"),
METHOD(&Layer::setPaintProperty, "nativeSetPaintProperty"),
METHOD(&Layer::setFilter, "nativeSetFilter"),
+ METHOD(&Layer::getFilter, "nativeGetFilter"),
METHOD(&Layer::setSourceLayer, "nativeSetSourceLayer"),
METHOD(&Layer::getSourceLayer, "nativeGetSourceLayer"),
METHOD(&Layer::getMinZoom, "nativeGetMinZoom"),
diff --git a/platform/android/src/style/layers/layer.cpp.ejs b/platform/android/src/style/layers/layer.cpp.ejs
index 1debb096a3..b08f0ec4dc 100644
--- a/platform/android/src/style/layers/layer.cpp.ejs
+++ b/platform/android/src/style/layers/layer.cpp.ejs
@@ -48,12 +48,25 @@ namespace android {
// Property getters
<% for (const property of properties) { -%>
+<% if (property.name != 'heatmap-color') { -%>
jni::Object<jni::ObjectTag> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>(jni::JNIEnv& env) {
using namespace mbgl::android::conversion;
Result<jni::jobject*> converted = convert<jni::jobject*>(env, layer.as<mbgl::style::<%- camelize(type) %>Layer>()-><%- camelize(type) %>Layer::get<%- camelize(property.name) %>());
return jni::Object<jni::ObjectTag>(*converted);
}
+<% } else { -%>
+ jni::Object<jni::ObjectTag> HeatmapLayer::getHeatmapColor(jni::JNIEnv& env) {
+ using namespace mbgl::android::conversion;
+ auto propertyValue = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getHeatmapColor();
+ if (propertyValue.isUndefined()) {
+ propertyValue = layer.as<mbgl::style::HeatmapLayer>()->HeatmapLayer::getDefaultHeatmapColor();
+ }
+ Result<jni::jobject*> converted = convert<jni::jobject*>(env, propertyValue);
+ return jni::Object<jni::ObjectTag>(*converted);
+ }
+
+<% } -%>
<% if (property.transition) { -%>
jni::Object<TransitionOptions> <%- camelize(type) %>Layer::get<%- camelize(property.name) %>Transition(jni::JNIEnv& env) {
using namespace mbgl::android::conversion;
diff --git a/platform/android/src/style/layers/layer.hpp b/platform/android/src/style/layers/layer.hpp
index 78c3f80b48..2486b0dfa6 100644
--- a/platform/android/src/style/layers/layer.hpp
+++ b/platform/android/src/style/layers/layer.hpp
@@ -3,8 +3,9 @@
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/style/layer.hpp>
-
+#include "../../gson/json_array.hpp"
#include "../value.hpp"
+#include "../../gson/json_element.hpp"
#include <jni/jni.hpp>
@@ -68,6 +69,8 @@ public:
void setFilter(jni::JNIEnv&, jni::Array<jni::Object<>>);
+ jni::Object<gson::JsonElement> getFilter(jni::JNIEnv&);
+
void setSourceLayer(jni::JNIEnv&, jni::String);
jni::String getSourceLayer(jni::JNIEnv&);
diff --git a/platform/android/src/text/local_glyph_rasterizer.cpp b/platform/android/src/text/local_glyph_rasterizer.cpp
index ce1b0fc8fd..d232058d15 100644
--- a/platform/android/src/text/local_glyph_rasterizer.cpp
+++ b/platform/android/src/text/local_glyph_rasterizer.cpp
@@ -46,6 +46,7 @@ PremultipliedImage LocalGlyphRasterizer::drawGlyphBitmap(const std::string& font
jniFontFamily,
static_cast<jni::jboolean>(bold),
static_cast<jni::jchar>(glyphID));
+ jni::DeleteLocalRef(*env, jniFontFamily);
PremultipliedImage result = Bitmap::GetImage(*env, javaBitmap);
jni::DeleteLocalRef(*env, javaBitmap);
diff --git a/platform/darwin/docs/guides/For Style Authors.md.ejs b/platform/darwin/docs/guides/For Style Authors.md.ejs
index 7648d6f7ac..2ae6602224 100644
--- a/platform/darwin/docs/guides/For Style Authors.md.ejs
+++ b/platform/darwin/docs/guides/For Style Authors.md.ejs
@@ -178,21 +178,22 @@ source object is a member of one of the following subclasses of `MGLSource`:
In style JSON | In the SDK
--------------|-----------
+`vector` | `MGLVectorTileSource`
+`raster` | `MGLRasterTileSource`
+`raster-dem` | `MGLRasterDEMSource`
`geojson` | `MGLShapeSource`
-`raster` | `MGLRasterSource`
-`vector` | `MGLVectorSource`
`image` | `MGLImageSource`
`canvas` and `video` sources are not supported.
### Tile sources
-Raster and vector sources may be defined in TileJSON configuration files. This
-SDK supports the properties defined in the style specification, which are a
+Raster and vector tile sources may be defined in TileJSON configuration files.
+This SDK supports the properties defined in the style specification, which are a
subset of the keys defined in version 2.1.0 of the
[TileJSON](https://github.com/mapbox/tilejson-spec/tree/master/2.1.0)
specification. As an alternative to authoring a custom TileJSON file, you may
-supply various tile source options when creating a raster or vector source.
+supply various tile source options when creating a raster or vector tile source.
These options are detailed in the `MGLTileSourceOption` documentation:
In style JSON | In TileJSON | In the SDK
@@ -321,6 +322,11 @@ iOS.
<% } -%>
### Expression operators
+Many expression operators defined in the style specification have corresponding
+symbols to be used with the `+[NSExpression expressionWithFormat:]`,
+`+[NSExpression expressionForFunction:arguments:]`, or
+`+[NSExpression expressionForFunction:selectorName:arguments:]` method:
+
In style specification | Method, function, or predicate type | Format string syntax
-----------------------|-------------------------------------|---------------------
`array` | |
@@ -330,15 +336,15 @@ In style specification | Method, function, or predicate type | Format string syn
`string` | |
`to-boolean` | `boolValue` |
`to-color` | |
-`to-number` | `mgl_numberWithFallbackValues:` |
-`to-string` | `stringValue` |
+`to-number` | `mgl_numberWithFallbackValues:` | `CAST(zipCode, 'NSNumber')`
+`to-string` | `stringValue` | `CAST(ele, 'NSString')`
`typeof` | |
-`geometry-type` | |
-`id` | |
-`properties` | |
-`at` | |
+`geometry-type` | `NSExpression.geometryTypeVariableExpression` | `$geometryType`
+`id` | `NSExpression.featureIdentifierVariableExpression` | `$featureIdentifier`
+`properties` | `NSExpression.featureAttributesVariableExpression` | `$featureAttributes`
+`at` | `objectFrom:withIndex:` | `array[n]`
`get` | `+[NSExpression expressionForKeyPath:]` | Key path
-`has` | |
+`has` | `mgl_does:have:` | `mgl_does:have:(self, 'key')`
`length` | `count:` | `count({1, 2, 2, 3, 4, 7, 9})`
`!` | `NSNotPredicateType` | `NOT (p0 OR … OR pn)`
`!=` | `NSNotEqualToPredicateOperatorType` | `key != value`
@@ -349,20 +355,20 @@ In style specification | Method, function, or predicate type | Format string syn
`>=` | `NSGreaterThanOrEqualToPredicateOperatorType` | `key >= value`
`all` | `NSAndPredicateType` | `p0 AND … AND pn`
`any` | `NSOrPredicateType` | `p0 OR … OR pn`
-`case` | `+[NSExpression expressionForConditional:trueExpression:falseExpression:]` | `TERNARY(condition, trueExpression, falseExpression)`
-`coalesce` | |
-`match` | |
-`interpolate` | `mgl_interpolateWithCurveType:parameters:stops:` |
-`step` | `mgl_stepWithMinimum:stops:` |
-`let` | `mgl_expressionWithContext:` |
+`case` | `+[NSExpression expressionForConditional:trueExpression:falseExpression:]` or `MGL_IF` or `+[NSExpression mgl_expressionForConditional:trueExpression:falseExpresssion:]` | `TERNARY(1 = 2, YES, NO)` or `MGL_IF(1 = 2, YES, 2 = 2, YES, NO)`
+`coalesce` | `mgl_coalesce:` | `mgl_coalesce({x, y, z})`
+`match` | `MGL_MATCH` or `+[NSExpression mgl_expressionForMatchingExpression:inDictionary:defaultExpression:]` | `MGL_MATCH(x, 0, 'zero match', 1, 'one match', 'two match', 'default')`
+`interpolate` | `mgl_interpolate:withCurveType:parameters:stops:` or `+[NSExpression mgl_expressionForInterpolatingExpression:withCurveType:parameters:stops:]` |
+`step` | `mgl_step:withMinimum:stops:` or `+[NSExpression mgl_expressionForSteppingExpression:fromExpression:stops:]` |
+`let` | `mgl_expressionWithContext:` | `MGL_LET('ios', 11, 'macos', 10.13, $ios + $macos)`
`var` | `+[NSExpression expressionForVariable:]` | `$variable`
-`concat` | `stringByAppendingString:` |
+`concat` | `mgl_join:` or `-[NSExpression mgl_expressionByAppendingExpression:]` | `mgl_join({'Old', ' ', 'MacDonald'})`
`downcase` | `lowercase:` | `lowercase('DOWNTOWN')`
`upcase` | `uppercase:` | `uppercase('Elysian Fields')`
<% if (macOS) { -%>
`rgb` | `+[NSColor colorWithCalibratedRed:green:blue:alpha:]` |
`rgba` | `+[NSColor colorWithCalibratedRed:green:blue:alpha:]` |
-<% } else { %>
+<% } else { -%>
`rgb` | `+[UIColor colorWithRed:green:blue:alpha:]` |
`rgba` | `+[UIColor colorWithRed:green:blue:alpha:]` |
<% } -%>
@@ -373,27 +379,34 @@ In style specification | Method, function, or predicate type | Format string syn
`%` | `modulus:by:` |
`^` | `raise:toPower:` | `2 ** 2`
`+` | `add:to:` | `1 + 2`
-`acos` | |
-`asin` | |
-`atan` | |
-`cos` | |
+`abs` | `abs:` | `abs(-1)`
+`acos` | `mgl_acos:` | `mgl_acos(1)`
+`asin` | `mgl_asin:` | `mgl_asin(0)`
+`atan` | `mgl_atan:` | `mgl_atan(20)`
+`ceil` | `ceiling:` | `ceiling(0.99999)`
+`cos` | `mgl_cos:` | `mgl_cos(0)`
`e` | | `%@` representing `NSNumber` containing `M_E`
+`floor` | `floor:` | `floor(-0.99999)`
`ln` | `ln:` | `ln(2)`
`ln2` | | `%@` representing `NSNumber` containing `M_LN2`
`log10` | `log:` | `log(1)`
-`log2` | |
+`log2` | `mgl_log2:` | `mgl_log2(1024)`
`max` | `max:` | `max({1, 2, 2, 3, 4, 7, 9})`
`min` | `min:` | `min({1, 2, 2, 3, 4, 7, 9})`
`pi` | | `%@` representing `NSNumber` containing `M_PI`
-`sin` | |
+`round` | `mgl_round:` | `mgl_round(1.5)`
+`sin` | `mgl_sin:` | `mgl_sin(0)`
`sqrt` | `sqrt:` | `sqrt(2)`
-`tan` | |
-`zoom` | | `$zoom`
-`heatmap-density` | | `$heatmapDensity`
+`tan` | `mgl_tan:` | `mgl_tan(0)`
+`zoom` | `NSExpression.zoomLevelVariableExpression` | `$zoom`
+`heatmap-density` | `NSExpression.heatmapDensityVariableExpression` | `$heatmapDensity`
+
+For operators that have no corresponding `NSExpression` symbol, use the
+`MGL_FUNCTION()` format string syntax.
## Filtering sources
-You can filter a shape or vector source by setting the
+You can filter a shape or vector tile source by setting the
`MGLVectorStyleLayer.predicate` property to an `NSPredicate` object. Below is a
table of style JSON operators and the corresponding operators used in the
predicate format string:
diff --git a/platform/darwin/docs/guides/Migrating to Expressions.md.ejs b/platform/darwin/docs/guides/Migrating to Expressions.md.ejs
new file mode 100644
index 0000000000..addbf6940e
--- /dev/null
+++ b/platform/darwin/docs/guides/Migrating to Expressions.md.ejs
@@ -0,0 +1,212 @@
+<%
+ const os = locals.os;
+ const iOS = os === 'iOS';
+ const macOS = os === 'macOS';
+ const cocoaPrefix = iOS ? 'UI' : 'NS';
+ const guide = 'MigratingToExpressions';
+-%>
+<!--
+ This file is generated.
+ Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
+-->
+
+# Migrating from Style Functions to Expressions
+
+[Runtime Styling](runtime-styling.html) enables you to modify every aspect of the map’s appearance dynamically as a user interacts with your application. Developers can specify in advance how a layout or paint attribute will vary as the zoom level changes or how the appearance of individual features vary based on metadata provided by a content source.
+
+With Mapbox Maps SDK for <%- iOS ? 'iOS v4.0.0' : 'macOS v0.7.0' %>, style functions have been replaced with expressions. These provide even more tools for developers who want to style their maps dynamically. This guide outlines some tips for migrating from style functions to expressions, and offers an overview of some things that developers can do with expressions.
+
+An expression is represented at runtime by the `NSExpression` class. Expressions can be used to style paint and layout properties based on zoom level, data attributes, or a combination of the two.
+
+A constant expression can also be assigned to a style property. For example, the opacity of a fill style layer can be set to a constant value between 0 and 1.
+
+The documentation for each individual style layer property notes which non-constant expressions are enabled for that property. Style functions supported four interpolation modes: exponential, interval, categorical, and identity.
+
+This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php). Under each interpolation mode, the style function implementation will be shown, followed by the current syntax.
+
+For more information about how to work with GeoJSON data in our <%- os %> SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide. To learn more about supported expressions, see our ["Predicates and Expressions"](predicates-and-expressions.html) guide. The "Predicates and Expressions" guide also outlines Mapbox custom functions that can be used to dynamically style a map.
+
+## Stops
+Stops are dictionary keys that are associated with layer attribute values. Constant values no longer need to be wrapped as style values when they are values in a stops dictionary.
+
+
+Style function syntax:
+
+```swift
+let stops = [
+ 0: MGLStyleValue<UIColor>(rawValue: .yellow),
+ 2.5: MGLStyleValue(rawValue: .orange),
+ 5: MGLStyleValue(rawValue: .red),
+ 7.5: MGLStyleValue(rawValue: .blue),
+ 10: MGLStyleValue(rawValue: .white),
+]
+```
+
+Current syntax:
+<%- guideExample(guide, 'Stops', os) %>
+
+
+## Interpolation mode
+
+Style functions supported four interpolation modes: exponential/linear, interval, categorical, and identity. For more information about supported custom expressions, please see the "Predicates and Expressions" guide.
+
+### Linear
+
+`+[NSExpression(MGLAdditions) mgl_expressionForInterpolatingExpression:withCurveType:parameters:stops:]` takes the interpolation type as a parameter. If you previously used the default interpolation base, use the curve type `MGLExpressionInterpolationMode.linear`. See the [`mgl_interpolate:withCurveType:parameters:stops:`](predicates-and-expressions.html#code-mgl_interpolate-withcurvetype-parameters-stops-code) documentation for more details.
+
+The stops dictionary below, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value.
+
+Style function syntax:
+
+```swift
+let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
+let symbolSource = MGLSource(identifier: "source")
+let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbolSource)
+
+let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil)
+mapView.style?.addSource(source)
+
+let stops = [
+ 0: MGLStyleValue<UIColor>(rawValue: .yellow),
+ 2.5: MGLStyleValue(rawValue: .orange),
+ 5: MGLStyleValue(rawValue: .red),
+ 7.5: MGLStyleValue(rawValue: .blue),
+ 10: MGLStyleValue(rawValue: .white),
+]
+
+let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
+layer.circleColor = MGLStyleValue(interpolationMode: .exponential,
+ sourceStops: stops,
+ attributeName: "mag",
+ options: [.defaultValue: MGLStyleValue<UIColor>(rawValue: .green)])
+layer.circleRadius = MGLStyleValue(rawValue: 10)
+mapView.style?.insertLayer(layer, below: symbolLayer)
+```
+
+Current syntax:
+
+<%- guideExample(guide, 'Linear', os) %>
+
+### Exponential
+
+If you previously used an interpolation base greater than `0` (other than `1`), you can use `MGLExpressionInterpolationMode.exponential` as the curve type for `+[NSExpression(MGLAdditions) mgl_expressionForInterpolatingExpression:withCurveType:parameters:stops:]` or `'exponential'` as the curve type for [`mgl_interpolate:withCurveType:parameters:stops:`](predicates-and-expressions.html#code-mgl_interpolate-withcurvetype-parameters-stops-code). The `parameters` argument takes that interpolation base. This interpolates between values exponentially, creating an accelerated ramp effect.
+
+Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom. In order to convert camera style functions, use `$zoomLevel` or `MGL_FUNCTION('zoomLevel')` as the attribute key.
+
+<img src="img/data-driven-styling/exponential-function.png" height=344/>
+<img src="img/data-driven-styling/exponential-function-1.png" height=344/>
+
+The example below increases a layer’s `circleRadius` exponentially based on a map’s zoom level. The interpolation base is `1.5`.
+
+Style function syntax:
+
+```swift
+let stops = [
+ 12: MGLStyleValue<NSNumber>(rawValue: 0.5),
+ 14: MGLStyleValue(rawValue: 2),
+ 18: MGLStyleValue(rawValue: 18),
+]
+
+layer.circleRadius = MGLStyleValue(interpolationMode: .exponential,
+ cameraStops: stops,
+ options: [.interpolationBase: 1.5])
+```
+
+Current syntax:
+
+<%- guideExample(guide, 'Exponential', os) %>
+
+### Interval
+
+Steps, or intervals, create a range using the keys from the stops dictionary. The range is from the given key to just less than the next key. The attribute values that fall into that range are then styled using the layout or paint value assigned to that key. You can use the `+[NSExpression(MGLAdditions) mgl_expressionForSteppingExpression:fromExpression:stops:]` method or the custom function [`mgl_step:from:stops:`](predicates-and-expressions.html#code-mgl_step-from-stops-code) for cases where you previously used interval interpolation mode. The first parameter takes the feature attribute name and the second parameter (`from:`) optionally takes the default or fallback value for that function. The final parameter takes a stops dictionary as an argument.
+
+When we use the stops dictionary given above with an `'mgl_step:from:stops:'`, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on.
+
+Style function syntax:
+
+```swift
+let stops = [
+ 0: MGLStyleValue<UIColor>(rawValue: .yellow),
+ 2.5: MGLStyleValue(rawValue: .orange),
+ 5: MGLStyleValue(rawValue: .red),
+ 7.5: MGLStyleValue(rawValue: .blue),
+ 10: MGLStyleValue(rawValue: .white),
+]
+
+layer.circleColor = MGLStyleValue(interpolationMode: .interval,
+ sourceStops: stops,
+ attributeName: "mag",
+ options: [.defaultValue: MGLStyleValue<UIColor>(rawValue: .green)])
+````
+
+Current syntax:
+
+<%- guideExample(guide, 'Interval', os) %>
+
+### Categorical
+
+Categorical interpolation mode took a stops dictionary. If the value for a specified feature attribute name matched one in that stops dictionary, the style value for that attribute value would be used. Categorical style functions can now be replaced with `MGL_MATCH`.
+
+`MGL_MATCH` takes an initial condition, which in this case is an attribute key. This is followed by possible matches for that key and the value to assign to the layer property if there is a match. The final argument can be a default style value that is to be used if none of the specified values match.
+
+There are three main types of events in the USGS dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of blue to catch any events that do not fall into any of those categories.
+
+Style function syntax:
+
+```swift
+let categoricalStops = [
+ "earthquake": MGLStyleValue<UIColor>(rawValue: .orange),
+ "explosion": MGLStyleValue(rawValue: .red),
+ "quarry blast": MGLStyleValue(rawValue: .yellow),
+]
+
+layer.circleColor = MGLStyleValue(interpolationMode: .categorical,
+ sourceStops: categoricalStops,
+ attributeName: "type",
+ options: [.defaultValue: MGLStyleValue<UIColor>(rawValue: .blue)])
+```
+
+Current syntax:
+<%- guideExample(guide, 'Categorical', os) %>
+
+If your use case does not require a default value, you can either apply a predicate to your layer prior to styling it, or use the format string `"valueForKeyPath:"`.
+
+### Identity
+
+Identity interpolation mode used the attribute’s value as the style layer property value. In this example, you might set the `circleRadius` to the earthquake’s magnitude. In order to use a feature attribute value to style a layer property, set the property value to `[NSExpression expressionForKeyPath:]`, which take the feature attribute name as an argument.
+
+Style function syntax:
+
+```swift
+layer.circleRadius = MGLStyleValue(interpolationMode: .identity,
+ sourceStops: nil,
+ attributeName: "mag",
+ options: [.defaultValue: MGLStyleValue<NSNumber>(rawValue: 0)])
+```
+
+Current syntax:
+<%- guideExample(guide, 'Identity', os) %>
+
+![identity mode](img/data-driven-styling/identity.png)
+
+Some built-in functions can be applied to attribute values to style layer property values. To set the circle radius to three times the earthquake’s magnitude, create a `multiply:by:` function that takes the attribute value and the multiplier as arguments, or use a format string.
+
+<%- guideExample(guide, 'Multiply', os) %>
+
+![multiply magnitude](img/data-driven-styling/multiply.png)
+
+You can also cast attribute values in order to use them. One example is to cast an integer as an `NSString` and use it as a text value.
+
+<%- guideExample(guide, 'Cast', os) %>
+
+![cast a value](img/data-driven-styling/cast.png)
+
+### Constant Values
+
+For constant values that do not necessarily change based on camera or attribute values, use `[NSExpression expressionForConstantValue:]` (previously `[MGLStyleValue valueWithRawValue:]`).
+
+## Resources
+
+* [USGS Earthquake Feed](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php)
+* [For Style Authors](for-style-authors.html)
+* [Predicates and Expressions](predicates-and-expressions.html)
diff --git a/platform/darwin/docs/guides/Predicates and Expressions.md b/platform/darwin/docs/guides/Predicates and Expressions.md
index 19d98fd4c1..c3b3d39a52 100644
--- a/platform/darwin/docs/guides/Predicates and Expressions.md
+++ b/platform/darwin/docs/guides/Predicates and Expressions.md
@@ -19,6 +19,8 @@ based on the feature’s attributes. Use the `MGLVectorStyleLayer.predicate`
property to include only the features in the source layer that satisfy a
condition that you define.
+### Operators
+
The following comparison operators are supported:
`NSPredicateOperatorType` | Format string syntax
@@ -31,12 +33,17 @@ The following comparison operators are supported:
`NSNotEqualToPredicateOperatorType` | `key != value`<br />`key <> value`
`NSBetweenPredicateOperatorType` | `key BETWEEN { 32, 212 }`
+To test whether a feature has or lacks a specific attribute, compare the
+attribute to `NULL` or `NIL`. Predicates created using the
+`+[NSPredicate predicateWithValue:]` method are also supported. String
+operators and custom operators are not supported.
+
The following compound operators are supported:
`NSCompoundPredicateType` | Format string syntax
--------------------------|---------------------
`NSAndPredicateType` | `predicate1 AND predicate2`<br />`predicate1 && predicate2`
-`NSOrPredicateType` | `predicate1 OR predicate2`<br />`predicate1 || predicate2`
+`NSOrPredicateType` | `predicate1 OR predicate2`<br /><code>predicate1 &vert;&vert; predicate2</code>
`NSNotPredicateType` | `NOT predicate`<br />`!predicate`
The following aggregate operators are supported:
@@ -46,97 +53,101 @@ The following aggregate operators are supported:
`NSInPredicateOperatorType` | `key IN { 'iOS', 'macOS', 'tvOS', 'watchOS' }`
`NSContainsPredicateOperatorType` | `{ 'iOS', 'macOS', 'tvOS', 'watchOS' } CONTAINS key`
-To test whether a feature has or lacks a specific attribute, compare the
-attribute to `NULL` or `NIL`. Predicates created using the
-`+[NSPredicate predicateWithValue:]` method are also supported. String
-operators and custom operators are not supported.
+Operator modifiers such as `c` (for case insensitivity), `d` (for diacritic
+insensitivity), and `l` (for locale sensitivity) are unsupported for comparison
+and aggregate operators that are used in the predicate.
+
+### Operands
+
+Operands in predicates can be [variables](#variables), [key paths](#key-paths),
+or almost anything else that can appear
+[inside an expression](#using-expressions-to-configure-layout-and-paint-attributes).
+
+Automatic type casting is not performed. Therefore, a feature only matches a
+predicate if its value for the attribute in question is of the same type as the
+value specified in the predicate. Use the `CAST()` operator to convert a key
+path or variable into a matching type:
+
+* To cast a value to a number, use `CAST(key, 'NSNumber')`.
+* To cast a value to a string, use `CAST(key, 'NSString')`.
For details about the predicate format string syntax, consult the “Predicate
Format String Syntax” chapter of the
_[Predicate Programming Guide](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Predicates/AdditionalChapters/Introduction.html)_
in Apple developer documentation.
-The predicate's left-hand expression must be a string that identifies a feature
-attribute or, alternatively, one of the following special attributes:
+## Using expressions to configure layout and paint attributes
+
+An expression can contain subexpressions of various types. Each of the supported
+types of expressions is discussed below.
+
+### Constant values
+
+A constant value can be of any of the following types:
+
+In Objective-C | In Swift
+----------------------|---------
+`NSColor` (macOS)<br>`UIColor` (iOS) | `NSColor` (macOS)<br>`UIColor` (iOS)
+`NSString` | `String`
+`NSString` | `String`
+`NSNumber.boolValue` | `NSNumber.boolValue`
+`NSNumber.doubleValue` | `NSNumber.doubleValue`
+`NSArray<NSNumber>` | `[Float]`
+`NSArray<NSString>` | `[String]`
+`NSValue.CGVectorValue` (iOS)<br>`NSValue` containing `CGVector` (macOS) | `NSValue.cgVectorValue` (iOS)<br>`NSValue` containing `CGVector` (macOS)
+`NSValue.UIEdgeInsetsValue` (iOS)<br>`NSValue.edgeInsetsValue` (macOS) | `NSValue.uiEdgeInsetsValue` (iOS)<br>`NSValue.edgeInsetsValue` (macOS)
+
+For literal floating-point values, use `-[NSNumber numberWithDouble:]` instead
+of `-[NSNumber numberWithFloat:]` to avoid precision issues.
+
+### Key paths
+
+A key path expression refers to an attribute of the `MGLFeature` object being
+evaluated for display. For example, if a polygon’s `MGLFeature.attributes`
+dictionary contains the `floorCount` key, then the key path `floorCount` refers
+to the value of the `floorCount` attribute when evaluating that particular
+polygon.
+
+The following special attribute is also available on features that are produced
+as a result of clustering multiple point features together in a shape source:
<table>
<thead>
-<tr><th>Attribute</th><th>Meaning</th></tr>
+<tr><th>Attribute</th><th>Type</th><th>Meaning</th></tr>
</thead>
<tbody>
<tr>
- <td><code>$id</code></td>
- <td>
- A value that uniquely identifies the feature in the containing source.
- For details on the types of values that may be associated with this key,
- consult the documentation for the <code>MGLFeature</code> protocol’s
- <code>identifier</code> property.
- </td>
-</tr>
-<tr>
- <td><code>$type</code></td>
- <td>
- The type of geometry represented by the feature. A feature’s type is
- guaranteed to be one of the following strings:
- <ul>
- <li>
- <code>Point</code> for point features, corresponding to the
- <code>MGLPointAnnotation</code> class
- </li>
- <li>
- <code>LineString</code> for polyline features, corresponding to
- the <code>MGLPolyline</code> class
- </li>
- <li>
- <code>Polygon</code> for polygon features, corresponding to the
- <code>MGLPolygon</code> class
- </li>
- </ul>
- </td>
-</tr>
-<tr>
<td><code>point_count</code></td>
+ <td>Number</td>
<td>The number of point features in a given cluster.</td>
</tr>
</tbody>
</table>
-The predicate’s right-hand expression must be an `NSString` (to match strings)
-or `NSNumber` (to match numbers, including Boolean values) or an array of
-`NSString`s or `NSNumber`s, depending on the operator and the type of values
-expected for the attribute being tested. For floating-point values, use
-`-[NSNumber numberWithDouble:]` instead of `-[NSNumber numberWithFloat:]`
-to avoid precision issues.
+Some characters may not be used directly as part of a key path in a format
+string. For example, if a feature’s attribute is named `ISO 3166-1:2006`, an
+expression format string of `lowercase(ISO 3166-1:2006)` or a predicate format
+string of `ISO 3166-1:2006 == 'US-OH'` would raise an exception. Instead, use a
+`%K` placeholder or the `+[NSExpression expressionForKeyPath:]` initializer:
-Automatic type casting is not performed. Therefore, a feature only matches this
-predicate if its value for the attribute in question is of the same type as the
-value specified in the predicate. Also, operator modifiers such as `c` (for
-case insensitivity), `d` (for diacritic insensitivity), and `l` (for locale
-sensitivity) are unsupported for comparison and aggregate operators that are
-used in the predicate.
-
-It is possible to create expressions that contain special characters in the
-predicate format syntax. This includes the `$` in the `$id` and `$type` special
-style attributes and also `hyphen-minus` and `tag:subtag`. However, you must use
-`%K` in the format string to represent these variables:
-`@"%K == 'LineString'", @"$type"`.
+```objc
+[NSPredicate predicateWithFormat:@"%K == 'US-OH'", @"ISO 3166-1:2006"];
+[NSExpression expressionForFunction:@"lowercase:"
+ arguments:@[[NSExpression expressionForKeyPath:@"ISO 3166-1:2006"]]]
+```
-## Using expressions to configure layout and paint attributes
+```swift
+NSPredicate(format: "%K == 'US-OH'", "ISO 3166-1:2006")
+NSExpression(forFunction: "lowercase:",
+ arguments: [NSExpression(forKeyPath: "ISO 3166-1:2006")])
+```
### Functions
-#### Key paths
-
-A key path expression refers to an attribute of the `MGLFeature` object being
-evaluated for display. For example, if a polygon’s `MGLFeature.attributes`
-dictionary contains the `floorCount` key, then the key path `floorCount` refers
-to the value of the `floorCount` attribute when evaluating that particular
-polygon.
-
-#### Predefined functions
-
Of the
-[functions predefined by the `+[NSExpression expressionForFunction:arguments:]` method](https://developer.apple.com/documentation/foundation/nsexpression/1413747-init#discussion),
+[functions predefined](https://developer.apple.com/documentation/foundation/nsexpression/1413747-init#discussion)
+by the
+[`+[NSExpression expressionForFunction:arguments:]` method](https://developer.apple.com/documentation/foundation/nsexpression/1413747-init),
the following subset is supported in layer attribute values:
Initializer parameter | Format string syntax
@@ -163,8 +174,13 @@ Initializer parameter | Format string syntax
`uppercase:` | `uppercase('Elysian Fields')`
`lowercase:` | `lowercase('DOWNTOWN')`
`noindex:` | `noindex(0 + 2 + c)`
+`length:` | `length('Wapakoneta')`
+`castObject:toType:` | `CAST(ele, 'NSString')`<br>`CAST(ele, 'NSNumber')`
-The following predefined functions are not supported:
+A number of [Mapbox-specific functions](#mapbox-specific-functions) are also
+available.
+
+The following predefined functions are **not** supported:
Initializer parameter | Format string syntax
----------------------|---------------------
@@ -182,199 +198,65 @@ Initializer parameter | Format string syntax
`onesComplement:` | `onesComplement(255)`
`distanceToLocation:fromLocation:` | `distanceToLocation:fromLocation:(there, here)`
-#### Mapbox-specific functions
+### Conditionals
-For compatibility with the Mapbox Style Specification, the following functions
-are defined by this SDK for use with style layers. Because these functions are
-not predefined by `NSExpression`, you must use the
-`+[NSExpression expressionForFunction:selectorName:arguments:]` method or the
-`FUNCTION()` format string syntax instead.
+Conditionals are supported via the built-in
+`+[NSExpression expressionForConditional:trueExpression:falseExpression:]`
+method and `TERNARY()` operator. If you need to express multiple cases
+(“else-if”), you can either nest a conditional within a conditional or use the
+[`MGL_IF()`](#code-mgl_if-code) or [`MGL_MATCH()`](#code-mgl_match-code) function.
+
+### Aggregates
+
+Aggregate expressions can contain arrays of expressions. In some cases, it is
+possible to use the array itself instead of wrapping the array in an aggregate
+expression.
+
+### Variables
+
+The following variables are defined by this SDK for use with style layers:
<table>
<thead>
-<tr><th>Selector name</th><th>Target</th><th>Arguments</th><th>Returns</th></tr>
+<tr><th>Variable</th><th>Type</th><th>Meaning</th></tr>
</thead>
<tbody>
<tr>
- <td><code>boolValue</code></td>
+ <td><code>$featureIdentifier</code></td>
<td>
- An `NSExpression` that evaluates to a number or string.
+ Any
+ <a href="working-with-geojson-data.html#about-geojson-deserialization">GeoJSON data type</a>
</td>
- <td></td>
<td>
- A Boolean representation of the target: `FALSE` when then input is an
- empty string, 0, `FALSE`, `NIL`, or NaN, otherwise `TRUE`.
+ A value that uniquely identifies the feature in the containing source.
+ This variable corresponds to the
+ <code>NSExpression.featureIdentifierVariableExpression</code> property.
</td>
</tr>
<tr>
- <td><code>mgl_expressionWithContext:</code></td>
+ <td><code>$geometryType</code></td>
+ <td>String</td>
<td>
- An `NSExpression` that may contain references to the variables defined in
- the context dictionary.
- </td>
- <td>
- An `NSDictionary` with `NSString`s as keys and `NSExpression`s as values.
- Each key is a variable name and each value is the variable’s value within
- the target expression.
- </td>
- <td>
- The target expression with variable subexpressions replaced with the
- values defined in the context dictionary.
- </td>
-</tr>
-<tr>
- <td><code>mgl_interpolateWithCurveType:parameters:stops:</code></td>
- <td>
- An `NSExpression` that evaluates to a number and contains a variable or
- key path expression.
- </td>
- <td>
- The first argument is one of the following strings denoting curve types:
- `linear`, `exponential`, or `cubic-bezier`.
-
- The second argument is an expression providing parameters for the curve:
-
- <ul>
- <li>If the curve type is `linear`, the argument is `NIL`.</li>
- <li>
- If the curve type is `exponential`, the argument is an expression
- that evaluates to a number, specifying the base of the exponential
- interpolation.
- </li>
- <li>
- If the curve type is `cubic-bezier`, the argument is an array or
- aggregate expression containing four expressions, each evaluating to
- a number. The four numbers are control points for the cubic Bézier
- curve.
- </li>
- </ul>
-
- The third argument is an `NSDictionary` object representing the
- interpolation’s stops, with numeric zoom levels as keys and expressions as
- values.
- </td>
- <td>
- A value interpolated along the continuous mathematical function defined by
- the arguments, with the target as the input to the function.
- </td>
-</tr>
-<tr>
- <td>
- <code>mgl_numberWithFallbackValues:</code>,
- <code>doubleValue</code>,
- <code>floatValue</code>,
- <code>decimalValue</code>
- </td>
- <td>
- An `NSExpression` that evaluates to a Boolean value, number, or string.
- </td>
- <td>
- Zero or more `NSExpression`s, each evaluating to a Boolean value or
- string.
- </td>
- <td>
- A numeric representation of the target:
- <ul>
- <li>If the target is `NIL` or `FALSE`, the result is 0.</li>
- <li>If the target is true, the result is 1.</li>
- <li>
- If the target is a string, it is converted to a number as specified
- by the
- “<a href="https://tc39.github.io/ecma262/#sec-tonumber-applied-to-the-string-type">ToNumber Applied to the String Type</a>”
- algorithm of the ECMAScript Language Specification.
- </li>
- <li>
- If multiple values are provided, each one is evaluated in order
- until the first successful conversion is obtained.
- </li>
- </ul>
- </td>
-</tr>
-<tr>
- <td><code>mgl_stepWithMinimum:stops:</code></td>
- <td>
- An `NSExpression` that evaluates to a number and contains a variable or
- key path expression.
- </td>
- <td>
- The first argument is an expression that evaluates to a number, specifying
- the minimum value in case the target is less than any of the stops in the
- second argument.
-
- The second argument is an `NSDictionary` object representing the
- interpolation’s stops, with numeric zoom levels as keys and expressions as
- values.
- </td>
- <td>
- The output value of the stop whose key is just less than the evaluated
- target, or the minimum value if the target is less than the least of the
- stops’ keys.
- </td>
-</tr>
-<tr>
- <td><code>stringByAppendingString:</code></td>
- <td>
- An `NSExpression` that evaluates to a string.
- </td>
- <td>
- One or more `NSExpression`s, each evaluating to a string.
- </td>
- <td>
- The target string with each of the argument strings appended in order.
- </td>
-</tr>
-<tr>
- <td><code>stringValue</code></td>
- <td>
- An `NSExpression` that evaluates to a Boolean value, number, or string.
- </td>
- <td></td>
- <td>
- A string representation of the target:
- <ul>
- <li>If the target is `NIL`, the result is the string `null`.</li>
- <li>
- If the target is a Boolean value, the result is the string `true` or
- `false`.
- </li>
- <li>
- If the target is a number, it is converted to a string as specified
- by the
- “<a href="https://tc39.github.io/ecma262/#sec-tostring-applied-to-the-number-type">NumberToString</a>”
- algorithm of the ECMAScript Language Specification.
- </li>
- <li>
- If the target is a color, it is converted to a string of the form
- `rgba(r,g,b,a)`, where <var>r</var>, <var>g</var>, and <var>b</var>
- are numerals ranging from 0 to 255 and <var>a</var> ranges from 0 to
- 1.
- </li>
- <li>
- Otherwise, the target is converted to a string in the format
- specified by the
- [`JSON.stringify()`](https://tc39.github.io/ecma262/#sec-json.stringify)
- function of the ECMAScript Language Specification.
- </li>
- </ul>
+ The type of geometry represented by the feature. A feature’s type is one
+ of the following strings:
+ <ul>
+ <li>
+ <code>Point</code> for point features, corresponding to the
+ <code>MGLPointAnnotation</code> class
+ </li>
+ <li>
+ <code>LineString</code> for polyline features, corresponding to
+ the <code>MGLPolyline</code> class
+ </li>
+ <li>
+ <code>Polygon</code> for polygon features, corresponding to the
+ <code>MGLPolygon</code> class
+ </li>
+ </ul>
+ This variable corresponds to the
+ <code>NSExpression.geometryTypeVariableExpression</code> property.
</td>
</tr>
-</tbody>
-</table>
-
-Some of these functions are defined as methods on their respective target
-classes, but you should not call them directly outside the context of an
-expression, because the result may differ from the evaluated expression’s result
-or may result in undefined behavior.
-
-### Variables
-
-The following variables are defined by this SDK for use with style layers:
-
-<table>
-<thead>
-<tr><th>Variable</th><th>Type</th><th>Meaning</th></tr>
-</thead>
-<tbody>
<tr>
<td><code>$heatmapDensity</code></td>
<td>Number</td>
@@ -383,7 +265,9 @@ The following variables are defined by this SDK for use with style layers:
<a href="https://en.wikipedia.org/wiki/Kernel_density_estimation">kernel density estimation</a>
of a screen point in a heatmap layer; in other words, a relative measure
of how many data points are crowded around a particular pixel. This
- variable can only be used with the `heatmapColor` property.
+ variable can only be used with the <code>heatmapColor</code> property.
+ This variable corresponds to the
+ <code>NSExpression.heatmapDensityVariableExpression</code> property.
</td>
</tr>
<tr>
@@ -392,7 +276,8 @@ The following variables are defined by this SDK for use with style layers:
<td>
The current zoom level. In style layout and paint properties, this
variable may only appear as the target of a top-level interpolation or
- step expression.
+ step expression. This variable corresponds to the
+ <code>NSExpression.zoomLevelVariableExpression</code> property.
</td>
</tr>
</tbody>
@@ -404,11 +289,601 @@ of a [Mapbox-specific function](#mapbox-specific-functions) that takes an
`NSDictionary` as an argument:
```objc
-[NSExpression expressionWithFormat:@"FUNCTION($floorCount + 1, 'mgl_expressionWithContext:', %@)",
- {@"floorCount": @2}];
+[NSExpression expressionWithFormat:@"MGL_LET('floorCount', 2, $floorCount + 1)"];
```
```swift
-NSExpression(format: "FUNCTION($floorCount + 1, 'mgl_expressionWithContext:', %@)",
- ["floorCount": 2])
+NSExpression(format: "MGL_LET(floorCount, 2, $floorCount + 1)")
```
+
+## Mapbox-specific functions
+
+For compatibility with the Mapbox Style Specification, the following functions
+are defined by this SDK. When setting a style layer property, you can call these
+functions just like the predefined functions above, using either the
+`+[NSExpression expressionForFunction:arguments:]` method or a convenient format
+string syntax:
+
+### `mgl_does:have:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_does:have:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>mgl_does:have:(SELF, '🧀🍔')</code> or <code>mgl_does:have:(%@, '🧀🍔')</code></dd>
+</dl>
+
+Returns a Boolean value indicating whether the dictionary has a value for the
+key or whether the evaluated object (`SELF`) has a value for the feature
+attribute. Compared to the [`mgl_has:`](#code-mgl_has-code) custom function,
+that function’s target is instead passed in as the first argument to this
+function. Both functions are equivalent to the syntax `key != NIL` or
+`%@[key] != NIL` but can be used outside of a predicate.
+
+### `mgl_interpolate:withCurveType:parameters:stops:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_interpolate:withCurveType:parameters:stops:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>mgl_interpolate:withCurveType:parameters:stops:(x, 'linear', nil, %@)</code></dd>
+</dl>
+
+Produces continuous, smooth results by interpolating between pairs of input and
+output values (“stops”). Compared to the
+[`mgl_interpolateWithCurveType:parameters:stops:`](#code-mgl_interpolatewithcurvetype-parameters-stops-code)
+custom function, the input expression (that function’s target) is instead passed
+in as the first argument to this function.
+
+### `mgl_step:from:stops:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_step:from:stops:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>mgl_step:from:stops:(x, 11, %@)</code></dd>
+</dl>
+
+Produces discrete, stepped results by evaluating a piecewise-constant function
+defined by pairs of input and output values ("stops"). Compared to the
+[`mgl_stepWithMinimum:stops:`](#code-mgl_stepwithminimum-stops-code) custom
+function, the input expression (that function’s target) is instead passed in as
+the first argument to this function.
+
+### `mgl_join:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_join:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>mgl_join({'Old', 'MacDonald'})</code></dd>
+</dl>
+
+Returns the result of concatenating together all the elements of an array in
+order. Compared to the
+[`stringByAppendingString:`](#code-stringbyappendingstring-code) custom
+function, this function takes only one argument, which is an aggregate
+expression containing the strings to concatenate.
+
+### `mgl_acos:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_acos:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>mgl_acos(1)</code></dd>
+</dl>
+
+Returns the arccosine of the number.
+
+This function corresponds to the
+[`acos`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-acos)
+operator in the Mapbox Style Specification.
+
+### `mgl_asin:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_asin:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>mgl_asin(0)</code></dd>
+</dl>
+
+Returns the arcsine of the number.
+
+This function corresponds to the
+[`asin`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-asin)
+operator in the Mapbox Style Specification.
+
+### `mgl_atan:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_atan:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>mgl_atan(20)</code></dd>
+</dl>
+
+Returns the arctangent of the number.
+
+This function corresponds to the
+[`atan`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-atan)
+operator in the Mapbox Style Specification.
+
+### `mgl_cos:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_cos:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>mgl_cos(0)</code></dd>
+</dl>
+
+Returns the cosine of the number.
+
+This function corresponds to the
+[`cos`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-cos)
+operator in the Mapbox Style Specification.
+
+### `mgl_log2:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_log2:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>mgl_log2(1024)</code></dd>
+</dl>
+
+Returns the base-2 logarithm of the number.
+
+This function corresponds to the
+[`log2`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-log2)
+operator in the Mapbox Style Specification.
+
+### `mgl_round:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_round:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>mgl_round(1.5)</code></dd>
+</dl>
+
+Returns the number rounded to the nearest integer. If the number is halfway
+between two integers, this function rounds it away from zero.
+
+This function corresponds to the
+[`round`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-round)
+operator in the Mapbox Style Specification.
+
+### `mgl_sin:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_sin:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>mgl_sin(0)</code></dd>
+</dl>
+
+Returns the sine of the number.
+
+This function corresponds to the
+[`sin`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-sin)
+operator in the Mapbox Style Specification.
+
+### `mgl_tan:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_tan:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>mgl_tan(0)</code></dd>
+</dl>
+
+Returns the tangent of the number.
+
+This function corresponds to the
+[`tan`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-tan)
+operator in the Mapbox Style Specification.
+
+### `mgl_coalesce:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_coalesce:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>mgl_coalesce({x, y, z})</code></dd>
+</dl>
+
+Returns the first non-`nil` value from an array of expressions.
+
+This function corresponds to the
+[`coalesce`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-coalesce)
+operator in the Mapbox Style Specification.
+
+### `MGL_LET`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>MGL_LET:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>MGL_LET('age', uppercase('old'), 'name', uppercase('MacDonald'), mgl_join({$age, $name}))</code></dd>
+<dt>Arguments:</dt>
+<dd>
+ Any number of variable names interspersed with their assigned
+ <code>NSExpression</code> values, followed by an <code>NSExpression</code>
+ that may contain references to those variables.
+</dd>
+</dl>
+
+Returns the result of evaluating an expression with the given variable values.
+Compared to the
+[`mgl_expressionWithContext:`](#code-mgl_expressionwithcontext-code) custom
+function, this function takes the variable names and values inline before the
+expression that contains references to those variables.
+
+### `MGL_MATCH`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>MGL_MATCH:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>MGL_MATCH(x, 0, 'zero match', 1, 'one match', 'two match', 'default')</code></dd>
+<dt>Arguments:</dt>
+<dd>
+ An input expression, then any number of argument pairs, followed by a default
+ expression. Each argument pair consists of a constant value followed by an
+ expression to produce as a result of matching that constant value.
+</dd>
+</dl>
+
+Returns the result of matching the input expression against the given constant
+values.
+
+This function corresponds to the
+`+[NSExpression(MGLAdditions) mgl_expressionForMatchingExpression:inDictionary:defaultExpression:]`
+method and the
+[`match`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-match)
+operator in the Mapbox Style Specification.
+
+### `MGL_IF`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>MGL_IF:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>MGL_IF(1 = 2, YES, 2 = 2, YES, NO)</code></dd>
+<dt>Arguments:</dt>
+<dd>
+ Alternating <code>NSPredicate</code> conditionals and resulting expressions,
+ followed by a default expression.
+</dd>
+</dl>
+
+Returns the first expression that meets the condition; otherwise, the default
+value. Unlike
+`+[NSExpression expressionForConditional:trueExpression:falseExpression:]` or
+the `TERNARY()` syntax, this function can accept multiple “if else” conditions
+and is supported on iOS 8._x_ and macOS 10.10._x_; however, each conditional
+passed into this function must be wrapped in a constant expression.
+
+This function corresponds to the
+`+[NSExpression(MGLAdditions) mgl_expressionForConditional:trueExpression:falseExpresssion:]`
+method and the
+[`case`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-case)
+operator in the Mapbox Style Specification.
+
+### `MGL_FUNCTION`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>MGL_FUNCTION:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>MGL_FUNCTION('typeof', mystery)</code></dd>
+<dt>Arguments:</dt>
+<dd>
+ Any arguments required by the expression operator.
+</dd>
+</dl>
+
+An expression exactly as defined by the
+[Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions).
+
+## Custom functions
+
+The following custom functions are also available with the
+`+[NSExpression expressionForFunction:selectorName:arguments:]` method or the
+`FUNCTION()` format string syntax.
+
+Some of these functions are defined as methods on their respective target
+classes, but you should not call them directly outside the context of an
+expression, because the result may differ from the evaluated expression’s result
+or may result in undefined behavior.
+
+The Mapbox Style Specification defines some operators for which no custom
+function is available. To use these operators in an `NSExpression`, call the
+[`MGL_FUNCTION()`](#code-mgl_function-code) function with the same arguments
+that the operator expects.
+
+### `boolValue`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>boolValue</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>FUNCTION(1, 'boolValue')</code></dd>
+<dt>Target:</dt>
+<dd>
+ An <code>NSExpression</code> that evaluates to a number or string.
+</dd>
+<dt>Arguments:</dt>
+<dd>None.</dd>
+</dl>
+
+A Boolean representation of the target: <code>FALSE</code> when then input is an
+empty string, 0, <code>FALSE</code>, <code>NIL</code>, or <code>NaN</code>,
+otherwise <code>TRUE</code>.
+
+### `mgl_has:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_has:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>FUNCTION($featureAttributes, 'mgl_has:', '🧀🍔')</code></dd>
+<dt>Target:</dt>
+<dd>
+ An <code>NSExpression</code> that evaluates to an <code>NSDictionary</code>
+ or the evaluated object (<code>SELF</code>).
+</dd>
+<dt>Arguments:</dt>
+<dd>
+ An <code>NSExpression</code> that evaluates to an <code>NSString</code>
+ representing the key to look up in the dictionary or the feature attribute to
+ look up in the evaluated object (see <code>MGLFeature.attributes</code>).
+</dd>
+</dl>
+
+<code>true</code> if the dictionary has a value for the key or if the evaluated
+object has a value for the feature attribute.
+
+This function corresponds to the
+[`has`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-has)
+operator in the Mapbox Style Specification. See also the
+[`mgl_does:have:`](#code-mgl_does-have-code) function, which is used on its own
+without the `FUNCTION()` operator. You can also check whether an object has an
+attribute by comparing the key path to `NIL`, for example `cheeseburger != NIL`
+or `burger.cheese != NIL`
+
+### `mgl_expressionWithContext:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_expressionWithContext:</code></dd>
+<dt>Format string syntax:</dt>
+<dd>
+ <code>FUNCTION($ios + $macos, 'mgl_expressionWithContext:', %@)</code> with
+ a dictionary containing <code>ios</code> and <code>macos</code> keys
+</dd>
+<dt>Target:</dt>
+<dd>
+ An <code>NSExpression</code> that may contain references to the variables
+ defined in the context dictionary.
+</dd>
+<dt>Arguments:</dt>
+<dd>
+ An <code>NSDictionary</code> with <code>NSString</code>s as keys and
+ <code>NSExpression</code>s as values. Each key is a variable name and each
+ value is the variable’s value within the target expression.
+</dd>
+</dl>
+
+The target expression with variable subexpressions replaced with the values
+defined in the context dictionary.
+
+This function corresponds to the
+[`let`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-let)
+operator in the Mapbox Style Specification. See also the
+[`MGL_LET`](#code-mgl_let-code) function, which is used on its own without the
+`FUNCTION()` operator.
+
+### `mgl_interpolateWithCurveType:parameters:stops:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_interpolateWithCurveType:parameters:stops:</code></dd>
+<dt>Format string syntax:</dt>
+<dd>
+ <code>FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', NIL, %@)</code>
+ with a dictionary containing zoom levels or other constant values as keys
+</dd>
+<dt>Target:</dt>
+<dd>
+ An <code>NSExpression</code> that evaluates to a number and contains a
+ variable or key path expression.
+</dd>
+<dt>Arguments:</dt>
+<dd>
+ The first argument is one of the following strings denoting curve types:
+ <code>linear</code>, <code>exponential</code>, or <code>cubic-bezier</code>.
+
+ The second argument is an expression providing parameters for the curve:
+
+ <ul>
+ <li>If the curve type is <code>linear</code>, the argument is <code>NIL</code>.</li>
+ <li>
+ If the curve type is <code>exponential</code>, the argument is an
+ expression that evaluates to a number, specifying the base of the
+ exponential interpolation.
+ </li>
+ <li>
+ If the curve type is <code>cubic-bezier</code>, the argument is an
+ array or aggregate expression containing four expressions, each
+ evaluating to a number. The four numbers are control points for the
+ cubic Bézier curve.
+ </li>
+ </ul>
+
+ The third argument is an <code>NSDictionary</code> object representing the
+ interpolation’s stops, with numeric zoom levels as keys and expressions as
+ values.
+</dd>
+</dl>
+
+A value interpolated along the continuous mathematical function defined by the
+arguments, with the target as the input to the function.
+
+The input expression is matched against the keys in the stop dictionary. The
+keys may be feature attribute values, zoom levels, or heatmap densities. The
+values may be constant values or `NSExpression` objects. For example, you can
+use a stop dictionary with the zoom levels 0, 10, and 20 as keys and the colors
+yellow, orange, and red as the values.
+
+This function corresponds to the
+`+[NSExpression(MGLAdditions) mgl_expressionForInterpolatingExpression:withCurveType:parameters:stops:]`
+method and the
+[`interpolate`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-interpolate)
+operator in the Mapbox Style Specification. See also the
+[`mgl_interpolate:withCurveType:parameters:stops:`](#code-mgl_interpolate-withcurvetype-parameters-stops-code)
+function, which is used on its own without the `FUNCTION()` operator.
+
+### `mgl_numberWithFallbackValues:`
+
+<dl>
+<dt>Selector:</dt>
+<dd>
+ <code>mgl_numberWithFallbackValues:</code>,
+ <code>doubleValue</code>,
+ <code>floatValue</code>, or
+ <code>decimalValue</code>
+</dd>
+<dt>Format string syntax:</dt>
+<dd><code>FUNCTION(ele, 'mgl_numberWithFallbackValues:', 0)</code></dd>
+<dt>Target:</dt>
+<dd>
+ An <code>NSExpression</code> that evaluates to a Boolean value, number, or
+ string.
+</dd>
+<dt>Arguments:</dt>
+<dd>
+ Zero or more <code>NSExpression</code>s, each evaluating to a Boolean value
+ or string.
+</dd>
+</dl>
+
+A numeric representation of the target:
+
+* If the target is <code>NIL</code> or <code>FALSE</code>, the result is 0.
+* If the target is true, the result is 1.
+ * If the target is a string, it is converted to a number as specified by the
+ “[ToNumber Applied to the String Type](https://tc39.github.io/ecma262/#sec-tonumber-applied-to-the-string-type)”
+ algorithm of the ECMAScript Language Specification.
+ * If multiple values are provided, each one is evaluated in order until the
+ first successful conversion is obtained.
+
+This function corresponds to the
+[`to-number`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-to-number)
+operator in the Mapbox Style Specification. You can also cast a value to a
+number by passing the value and the string `NSNumber` into the `CAST()`
+operator.
+
+### `mgl_stepWithMinimum:stops:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>mgl_stepWithMinimum:stops:</code></dd>
+<dt>Format string syntax:</dt>
+<dd>
+ <code>FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', 0, %@)</code> with
+ a dictionary with zoom levels or other constant values as keys
+</dd>
+<dt>Target:</dt>
+<dd>
+ An <code>NSExpression</code> that evaluates to a number and contains a
+ variable or key path expression.
+</dd>
+<dt>Arguments:</dt>
+<dd>
+ The first argument is an expression that evaluates to a number, specifying
+ the minimum value in case the target is less than any of the stops in the
+ second argument.
+
+ The second argument is an <code>NSDictionary</code> object representing the
+ interpolation’s stops, with numeric zoom levels as keys and expressions as
+ values.
+</dd>
+</dl>
+
+The output value of the stop whose key is just less than the evaluated target,
+or the minimum value if the target is less than the least of the stops’ keys.
+
+The input expression is matched against the keys in the stop dictionary. The
+keys may be feature attribute values, zoom levels, or heatmap densities. The
+values may be constant values or `NSExpression` objects. For example, you can
+use a stop dictionary with the zoom levels 0, 10, and 20 as keys and the colors
+yellow, orange, and red as the values.
+
+This function corresponds to the
+`+[NSExpression(MGLAdditions) mgl_expressionForSteppingExpression:fromExpression:stops:]`
+method and the
+[`step`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-step)
+operator in the Mapbox Style Specification.
+
+### `stringByAppendingString:`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>stringByAppendingString:</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>FUNCTION('Old', 'stringByAppendingString:', 'MacDonald')</code></dd>
+<dt>Target:</dt>
+<dd>An <code>NSExpression</code> that evaluates to a string.</dd>
+<dt>Arguments:</dt>
+<dd>One or more <code>NSExpression</code>s, each evaluating to a string.</dd>
+</dl>
+
+The target string with each of the argument strings appended in order.
+
+This function corresponds to the
+`-[NSExpression(MGLAdditions) mgl_expressionByAppendingExpression:]`
+method and is similar to the
+[`concat`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-concat)
+operator in the Mapbox Style Specification. See also the
+[`mgl_join:`](#code-mgl_join-code) function, which concatenates multiple
+expressions and is used on its own without the `FUNCTION()` operator.
+
+### `stringValue`
+
+<dl>
+<dt>Selector:</dt>
+<dd><code>stringValue</code></dd>
+<dt>Format string syntax:</dt>
+<dd><code>FUNCTION(ele, 'stringValue')</code></dd>
+<dt>Target:</dt>
+<dd>
+ An <code>NSExpression</code> that evaluates to a Boolean value, number, or
+ string.
+</dd>
+<dt>Arguments:</dt>
+<dd>None.</dd>
+</dl>
+
+A string representation of the target:
+
+* If the target is <code>NIL</code>, the result is the empty string.
+* If the target is a Boolean value, the result is the string `true` or `false`.
+* If the target is a number, it is converted to a string as specified by the
+ “[NumberToString](https://tc39.github.io/ecma262/#sec-tostring-applied-to-the-number-type)”
+ algorithm of the ECMAScript Language Specification.
+* If the target is a color, it is converted to a string of the form
+ `rgba(r,g,b,a)`, where <var>r</var>, <var>g</var>, and <var>b</var> are
+ numerals ranging from 0 to 255 and <var>a</var> ranges from 0 to 1.
+* Otherwise, the target is converted to a string in the format specified by the
+ [`JSON.stringify()`](https://tc39.github.io/ecma262/#sec-json.stringify)
+ function of the ECMAScript Language Specification.
+
+This function corresponds to the
+[`to-string`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-to-string)
+operator in the Mapbox Style Specification. You can also cast a value to a
+string by passing the value and the string `NSString` into the `CAST()`
+operator.
diff --git a/platform/darwin/docs/guides/Tile URL Templates.md.ejs b/platform/darwin/docs/guides/Tile URL Templates.md.ejs
index 78fb297138..2b1de65b42 100644
--- a/platform/darwin/docs/guides/Tile URL Templates.md.ejs
+++ b/platform/darwin/docs/guides/Tile URL Templates.md.ejs
@@ -10,12 +10,12 @@
-->
# Tile URL Templates
-`MGLTileSource` objects, specifically `MGLRasterSource` and `MGLVectorSource`
-objects, can be created using an initializer that accepts an array of tile URL
-templates. Tile URL templates are strings that specify the URLs of the vector
-tiles or raster tile images to load. A template resembles an absolute URL, but
-with any number of placeholder strings that the source evaluates based on the
-tile it needs to load. For example:
+`MGLTileSource` objects, specifically `MGLRasterTileSource` and
+`MGLVectorTileSource` objects, can be created using an initializer that accepts
+an array of tile URL templates. Tile URL templates are strings that specify the
+URLs of the vector tiles or raster tile images to load. A template resembles an
+absolute URL, but with any number of placeholder strings that the source
+evaluates based on the tile it needs to load. For example:
* `http://www.example.com/tiles/{z}/{x}/{y}.pbf` could be
evaluated as `http://www.example.com/tiles/14/6/9.pbf`.
@@ -62,7 +62,7 @@ all of which are optional:
<td>The tile’s zoom level. At zoom level 0, each tile covers the entire
world map; at zoom level 1, it covers ¼ of the world; at zoom level 2,
<sup>1</sup>⁄<sub>16</sub> of the world, and so on. For tiles loaded by
- a <code>MGLRasterSource</code> object, whether the tile zoom level
+ a <code>MGLRasterTileSource</code> object, whether the tile zoom level
matches the map’s current zoom level depends on the value of the
source’s tile size as specified in the
<code>MGLTileSourceOptionTileSize</code> key of the <code>options</code>
diff --git a/platform/darwin/docs/guides/Using Style Functions at Runtime.md.ejs b/platform/darwin/docs/guides/Using Style Functions at Runtime.md.ejs
deleted file mode 100644
index 61034a674f..0000000000
--- a/platform/darwin/docs/guides/Using Style Functions at Runtime.md.ejs
+++ /dev/null
@@ -1,99 +0,0 @@
-<%
- const os = locals.os;
- const iOS = os === 'iOS';
- const macOS = os === 'macOS';
- const cocoaPrefix = iOS ? 'UI' : 'NS';
- const guide = 'UsingStyleFunctionsAtRuntime';
--%>
-<!--
- This file is generated.
- Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
--->
-
-# Using Style Functions at Runtime
-
-[Runtime Styling](runtime-styling.html) enables you to modify every aspect of the map’s appearance dynamically as a user interacts with your application. Much of the runtime styling API allows you to specify _style functions_ instead of constant values. A style function allows you to specify in advance how a layout or paint attribute will vary as the zoom level changes or how the appearance of individual features vary based on metadata provided by a content source.
-
-Style functions spare you the inconvenience of manually calculating intermediate values between different zoom levels or creating a multitude of style layers to handle homogeneous features in the map content. For example, if your content source indicates the prices of hotels in an area, you can color-code the hotels by price, relying on a style function to smoothly interpolate among desired colors without having to specify the color for each exact price.
-
-_Data-driven styling_ specifically refers to the use of style functions to vary the map’s appearance based on data in a content source.
-
-You can also specify style functions in a style JSON file, to be applied automatically when the map loads. See the [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-js/style-spec/#types-function) for details.
-
-![available bikes](img/data-driven-styling/citibikes.png) ![subway lines](img/data-driven-styling/polylineExample.png)
-
-This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) and data-driven styling to style a map based on attributes. For more information about how to work with GeoJSON data in our iOS SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide.
-
-A style function is represented at runtime by the `MGLStyleFunction` class. There are three subclasses of `MGLStyleFunction`:
-
-* `MGLCameraStyleFunction` is a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level.
-* `MGLSourceStyleFunction` is a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake.
-* `MGLCompositeStyleFunction` is a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake.
-
-The documentation for each individual style layer property notes which style functions are enabled for that property.
-
-## Stops
-
-Stops are dictionary keys that are associated with layer attribute values. With feature attribute values as stops, you can use a dictionary with a zoom level for a key and an expression or constant value for the value. For example, you can use a stop dictionary with the zoom levels 0, 10, and 20 as keys and the colors yellow, orange, and red as the values. Alternatively, attribute values can be the keys.
-
-<%- guideExample(guide, 'Stops', os) %>
-
-## Interpolation mode
-
-The effect a key has on the style value is determined by the interpolation mode. There are four interpolation modes that can be used with a source style function: exponential, interval, categorical, and identity. You can also use exponential and interval interpolation modes with a camera style function.
-
-### Linear
-
-`MGLInterpolationModeExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation and doesn’t need to be included in the options dictionary.
-
-The stops dictionary below, for example, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value.
-
-<%- guideExample(guide, 'Linear', os) %>
-
-![exponential mode](img/data-driven-styling/exponential.png)
-
-### Exponential
-
-By combining `MGLInterpolationModeExponential` with an `MGLStyleFunctionOptionInterpolationBase` greater than `0` (other than `1`), you can interpolate between values exponentially, create an accelerated ramp effect.
-
-Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom.
-
-<img src="img/data-driven-styling/exponential-function.png" height=344/>
-<img src="img/data-driven-styling/exponential-function-1.png" height=344/>
-
-The example below increases a layer’s `circleRadius` exponentially based on a map’s zoom level. The `MGLStyleFunctionOptionInterpolationBase` is `1.5`.
-
-<%- guideExample(guide, 'Exponential', os) %>
-
-### Interval
-
-`MGLInterpolationModeInterval` creates a range using the keys from the stops dictionary. The range is from the given key to just less than the next key. The attribute values that fall into that range are then styled using the style value assigned to that key.
-
-When we use the stops dictionary given above with an interval interpolation mode, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on.
-
-<%- guideExample(guide, 'Interval', os) %>
-
-![interval mode](img/data-driven-styling/interval.png)
-
-### Categorical
-
-At each stop, `MGLInterpolationModeCategorical` produces an output value equal to the function input. We’re going to use a different stops dictionary than we did for the previous two modes.
-
-There are three main types of events in the dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of blue to catch any events that do not fall into any of those categories.
-
-<%- guideExample(guide, 'Categorical', os) %>
-
-![categorical mode](img/data-driven-styling/categorical1.png) ![categorical mode](img/data-driven-styling/categorical2.png)
-
-### Identity
-
-`MGLInterpolationModeIdentity` uses the attribute’s value as the style value. For example, you can set the `circleRadius` to the earthquake’s magnitude. Since the attribute value itself will be used as the style value, `sourceStops` should be set to `nil`.
-
-<%- guideExample(guide, 'Identity', os) %>
-
-![identity mode](img/data-driven-styling/identity.png)
-
-##Resources
-
-* [USGS](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php)
-* [For Style Authors](for-style-authors.html)
diff --git a/platform/darwin/docs/img/data-driven-styling/cast.png b/platform/darwin/docs/img/data-driven-styling/cast.png
new file mode 100644
index 0000000000..e5b40b4ffa
--- /dev/null
+++ b/platform/darwin/docs/img/data-driven-styling/cast.png
Binary files differ
diff --git a/platform/darwin/docs/img/data-driven-styling/categorical1.png b/platform/darwin/docs/img/data-driven-styling/categorical1.png
deleted file mode 100644
index 969846b41b..0000000000
--- a/platform/darwin/docs/img/data-driven-styling/categorical1.png
+++ /dev/null
Binary files differ
diff --git a/platform/darwin/docs/img/data-driven-styling/categorical2.png b/platform/darwin/docs/img/data-driven-styling/categorical2.png
deleted file mode 100644
index 5008c522ed..0000000000
--- a/platform/darwin/docs/img/data-driven-styling/categorical2.png
+++ /dev/null
Binary files differ
diff --git a/platform/darwin/docs/img/data-driven-styling/citibikes.png b/platform/darwin/docs/img/data-driven-styling/citibikes.png
deleted file mode 100644
index a616672a32..0000000000
--- a/platform/darwin/docs/img/data-driven-styling/citibikes.png
+++ /dev/null
Binary files differ
diff --git a/platform/darwin/docs/img/data-driven-styling/exponential-function-1.png b/platform/darwin/docs/img/data-driven-styling/exponential-function-1.png
index 6aa129a305..39a8a2a1e4 100644
--- a/platform/darwin/docs/img/data-driven-styling/exponential-function-1.png
+++ b/platform/darwin/docs/img/data-driven-styling/exponential-function-1.png
Binary files differ
diff --git a/platform/darwin/docs/img/data-driven-styling/exponential-function.png b/platform/darwin/docs/img/data-driven-styling/exponential-function.png
index c14969f0a8..f9824fc5e4 100644
--- a/platform/darwin/docs/img/data-driven-styling/exponential-function.png
+++ b/platform/darwin/docs/img/data-driven-styling/exponential-function.png
Binary files differ
diff --git a/platform/darwin/docs/img/data-driven-styling/exponential.png b/platform/darwin/docs/img/data-driven-styling/exponential.png
deleted file mode 100644
index 87ddc1350e..0000000000
--- a/platform/darwin/docs/img/data-driven-styling/exponential.png
+++ /dev/null
Binary files differ
diff --git a/platform/darwin/docs/img/data-driven-styling/identity.png b/platform/darwin/docs/img/data-driven-styling/identity.png
index 632ccdf3d5..3355694ec9 100644
--- a/platform/darwin/docs/img/data-driven-styling/identity.png
+++ b/platform/darwin/docs/img/data-driven-styling/identity.png
Binary files differ
diff --git a/platform/darwin/docs/img/data-driven-styling/interval.png b/platform/darwin/docs/img/data-driven-styling/interval.png
deleted file mode 100644
index d15aff2025..0000000000
--- a/platform/darwin/docs/img/data-driven-styling/interval.png
+++ /dev/null
Binary files differ
diff --git a/platform/darwin/docs/img/data-driven-styling/multiply.png b/platform/darwin/docs/img/data-driven-styling/multiply.png
new file mode 100644
index 0000000000..df42f243e1
--- /dev/null
+++ b/platform/darwin/docs/img/data-driven-styling/multiply.png
Binary files differ
diff --git a/platform/darwin/docs/img/data-driven-styling/polylineExample.png b/platform/darwin/docs/img/data-driven-styling/polylineExample.png
deleted file mode 100644
index cd9b39bae4..0000000000
--- a/platform/darwin/docs/img/data-driven-styling/polylineExample.png
+++ /dev/null
Binary files differ
diff --git a/platform/darwin/docs/theme/assets/css/jazzy.css.scss b/platform/darwin/docs/theme/assets/css/jazzy.css.scss
index 103ba601dc..ff6d2a374c 100644
--- a/platform/darwin/docs/theme/assets/css/jazzy.css.scss
+++ b/platform/darwin/docs/theme/assets/css/jazzy.css.scss
@@ -113,7 +113,12 @@ h2 {
}
h3 {
- @include heading(14px, 1em 0 0.3em);
+ @include heading(1.2rem, 1em 0 0.3em);
+}
+
+h3 > code {
+ font-weight: bold;
+ font-size: 1.2rem;
}
h4 {
@@ -386,7 +391,6 @@ pre code {
.nav-group-task[data-name="MGLStyleFunction"],
.nav-group-task[data-name="MGLStyleLayer"],
.nav-group-task[data-name="MGLTileSource"],
-.nav-group-task[data-name="MGLAbstractShapeSource"],
.nav-group-task[data-name="MGLVectorStyleLayer"] {
.nav-group-task-link::after {
@extend %nav-group-task-gloss;
diff --git a/platform/darwin/resources/da.lproj/Foundation.strings b/platform/darwin/resources/da.lproj/Foundation.strings
new file mode 100644
index 0000000000..d8d18f453c
--- /dev/null
+++ b/platform/darwin/resources/da.lproj/Foundation.strings
@@ -0,0 +1,297 @@
+/* Clock position format, long: {hours} o’clock */
+"CLOCK_FMT_LONG" = "%@ klokken";
+
+/* Clock position format, medium: {hours} o’clock */
+"CLOCK_FMT_MEDIUM" = "%@ klokken";
+
+/* Clock position format, short: {hours}:00 */
+"CLOCK_FMT_SHORT" = "%@:00";
+
+/* East, long */
+"COMPASS_E_LONG" = "øst";
+
+/* East, short */
+"COMPASS_E_SHORT" = "Ø";
+
+/* East by north, long */
+"COMPASS_EbN_LONG" = "øst via nord";
+
+/* East by north, short */
+"COMPASS_EbN_SHORT" = "ØvN";
+
+/* East by south, long */
+"COMPASS_EbS_LONG" = "øst via syd";
+
+/* East by south, short */
+"COMPASS_EbS_SHORT" = "ØvS";
+
+/* East-northeast, long */
+"COMPASS_ENE_LONG" = "øst-nordøst";
+
+/* East-northeast, short */
+"COMPASS_ENE_SHORT" = "ØNØ";
+
+/* East-southeast, long */
+"COMPASS_ESE_LONG" = "øst-sydøst";
+
+/* East-southeast, short */
+"COMPASS_ESE_SHORT" = "ØSØ";
+
+/* North, long */
+"COMPASS_N_LONG" = "nord";
+
+/* North, short */
+"COMPASS_N_SHORT" = "N";
+
+/* North by east, long */
+"COMPASS_NbE_LONG" = "nord via øst";
+
+/* North by east, short */
+"COMPASS_NbE_SHORT" = "NvØ";
+
+/* North by west, long */
+"COMPASS_NbW_LONG" = "nord via vest";
+
+/* North by west, short */
+"COMPASS_NbW_SHORT" = "NvV";
+
+/* Northeast, long */
+"COMPASS_NE_LONG" = "nordøst";
+
+/* Northeast, short */
+"COMPASS_NE_SHORT" = "NØ";
+
+/* Northeast by east, long */
+"COMPASS_NEbE_LONG" = "nordøst via øst";
+
+/* Northeast by east, short */
+"COMPASS_NEbE_SHORT" = "NØvØ";
+
+/* Northeast by north, long */
+"COMPASS_NEbN_LONG" = "nordøst via nord";
+
+/* Northeast by north, short */
+"COMPASS_NEbN_SHORT" = "NØvN";
+
+/* North-northeast, long */
+"COMPASS_NNE_LONG" = "nord-nordøst";
+
+/* North-northeast, short */
+"COMPASS_NNE_SHORT" = "NNØ";
+
+/* North-northwest, long */
+"COMPASS_NNW_LONG" = "nord-nordvest";
+
+/* North-northwest, short */
+"COMPASS_NNW_SHORT" = "NNV";
+
+/* Northwest, long */
+"COMPASS_NW_LONG" = "nordvest";
+
+/* Northwest, short */
+"COMPASS_NW_SHORT" = "NV";
+
+/* Northwest by north, long */
+"COMPASS_NWbN_LONG" = "nordvest via nord";
+
+/* Northwest by north, short */
+"COMPASS_NWbN_SHORT" = "NVvN";
+
+/* Northwest by west, long */
+"COMPASS_NWbW_LONG" = "nordvest via vest";
+
+/* Northwest by west, short */
+"COMPASS_NWbW_SHORT" = "NVvW";
+
+/* South, long */
+"COMPASS_S_LONG" = "syd";
+
+/* South, short */
+"COMPASS_S_SHORT" = "S";
+
+/* South by east, long */
+"COMPASS_SbE_LONG" = "syd via øst";
+
+/* South by east, short */
+"COMPASS_SbE_SHORT" = "SvØ";
+
+/* South by west, long */
+"COMPASS_SbW_LONG" = "syd via vest";
+
+/* South by west, short */
+"COMPASS_SbW_SHORT" = "SvV";
+
+/* Southeast, long */
+"COMPASS_SE_LONG" = "sydøst";
+
+/* Southeast, short */
+"COMPASS_SE_SHORT" = "SØ";
+
+/* Southeast by east, long */
+"COMPASS_SEbE_LONG" = "sydøst via øst";
+
+/* Southeast by east, short */
+"COMPASS_SEbE_SHORT" = "SØvØ";
+
+/* Southeast by south, long */
+"COMPASS_SEbS_LONG" = "sydøst via syd";
+
+/* Southeast by south, short */
+"COMPASS_SEbS_SHORT" = "SØvS";
+
+/* South-southeast, long */
+"COMPASS_SSE_LONG" = "syd-sydøst";
+
+/* South-southeast, short */
+"COMPASS_SSE_SHORT" = "SSØ";
+
+/* South-southwest, long */
+"COMPASS_SSW_LONG" = "syd-sydvest";
+
+/* South-southwest, short */
+"COMPASS_SSW_SHORT" = "SSV";
+
+/* Southwest, long */
+"COMPASS_SW_LONG" = "sydvest";
+
+/* Southwest, short */
+"COMPASS_SW_SHORT" = "SV";
+
+/* Southwest by south, long */
+"COMPASS_SWbS_LONG" = "sydvest via syd";
+
+/* Southwest by south, short */
+"COMPASS_SWbS_SHORT" = "SVvS";
+
+/* Southwest by west, long */
+"COMPASS_SWbW_LONG" = "sydvest via vest";
+
+/* Southwest by west, short */
+"COMPASS_SWbW_SHORT" = "SVvV";
+
+/* West, long */
+"COMPASS_W_LONG" = "vest";
+
+/* West, short */
+"COMPASS_W_SHORT" = "V";
+
+/* West by north, long */
+"COMPASS_WbN_LONG" = "vest via nord";
+
+/* West by north, short */
+"COMPASS_WbN_SHORT" = "VvN";
+
+/* West by south, long */
+"COMPASS_WbS_LONG" = "vest via syd";
+
+/* West by south, short */
+"COMPASS_WbS_SHORT" = "VvS";
+
+/* West-northwest, long */
+"COMPASS_WNW_LONG" = "vest-nordvest";
+
+/* West-northwest, short */
+"COMPASS_WNW_SHORT" = "VNV";
+
+/* West-southwest, long */
+"COMPASS_WSW_LONG" = "vest-sydvest";
+
+/* West-southwest, short */
+"COMPASS_WSW_SHORT" = "VSV";
+
+/* Degrees format, long */
+"COORD_DEG_LONG" = "%d grad(er)";
+
+/* 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$@ og %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$@, og %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" = "%@ øst";
+
+/* East longitude format, medium: {longitude} */
+"COORD_E_MEDIUM" = "%@ øst";
+
+/* East longitude format, short: {longitude} */
+"COORD_E_SHORT" = "%@Ø";
+
+/* Coordinate pair format, long: {latitude}, {longitude} */
+"COORD_FMT_LONG" = "%1$@ via %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 minut(ter)";
+
+/* Minutes format, medium: {minutes} */
+"COORD_MIN_MEDIUM" = "%d′";
+
+/* Minutes format, short: {minutes} */
+"COORD_MIN_SHORT" = "%d′";
+
+/* North latitude format, long: {latitude} */
+"COORD_N_LONG" = "%@ nord";
+
+/* North latitude format, medium: {latitude} */
+"COORD_N_MEDIUM" = "%@ nord";
+
+/* North latitude format, short: {latitude} */
+"COORD_N_SHORT" = "%@N";
+
+/* South latitude format, long: {latitude} */
+"COORD_S_LONG" = "%@ syd";
+
+/* South latitude format, medium: {latitude} */
+"COORD_S_MEDIUM" = "%@ syd";
+
+/* South latitude format, short: {latitude} */
+"COORD_S_SHORT" = "%@S";
+
+/* Seconds format, long */
+"COORD_SEC_LONG" = "%d sekunde(r)";
+
+/* Seconds format, medium: {seconds} */
+"COORD_SEC_MEDIUM" = "%d″";
+
+/* Seconds format, short: {seconds} */
+"COORD_SEC_SHORT" = "%d″";
+
+/* West longitude format, long: {longitude} */
+"COORD_W_LONG" = "%@ vest";
+
+/* West longitude format, medium: {longitude} */
+"COORD_W_MEDIUM" = "%@ vest";
+
+/* West longitude format, short: {longitude} */
+"COORD_W_SHORT" = "%@V";
+
+/* OpenStreetMap full name attribution */
+"OSM_FULL_NAME" = "OpenStreetMap";
+
+/* OpenStreetMap short name attribution */
+"OSM_SHORT_NAME" = "OSM";
+
diff --git a/platform/darwin/resources/da.lproj/Foundation.stringsdict b/platform/darwin/resources/da.lproj/Foundation.stringsdict
new file mode 100644
index 0000000000..17983b8aa8
--- /dev/null
+++ b/platform/darwin/resources/da.lproj/Foundation.stringsdict
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>COORD_DEG_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@degrees@</string>
+ <key>degrees</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d grad</string>
+ <key>other</key>
+ <string>%d grader</string>
+ </dict>
+ </dict>
+ <key>COORD_MIN_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@minutes@</string>
+ <key>minutes</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d minut</string>
+ <key>other</key>
+ <string>%d minutter</string>
+ </dict>
+ </dict>
+ <key>COORD_SEC_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@seconds@</string>
+ <key>seconds</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d sekund</string>
+ <key>other</key>
+ <string>%d sekunder</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/platform/darwin/resources/pt-PT.lproj/Foundation.stringsdict b/platform/darwin/resources/pt-PT.lproj/Foundation.stringsdict
new file mode 100644
index 0000000000..e99e86d98d
--- /dev/null
+++ b/platform/darwin/resources/pt-PT.lproj/Foundation.stringsdict
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>COORD_DEG_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@degrees@</string>
+ <key>degrees</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d grau</string>
+ <key>other</key>
+ <string>%d graus</string>
+ </dict>
+ </dict>
+ <key>COORD_MIN_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@minutes@</string>
+ <key>minutes</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d minuto</string>
+ <key>other</key>
+ <string>%d minutos</string>
+ </dict>
+ </dict>
+ <key>COORD_SEC_LONG</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@seconds@</string>
+ <key>seconds</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>%d segundo</string>
+ <key>other</key>
+ <string>%d segundos</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js
index 53a668d10b..c7b54b326a 100755
--- a/platform/darwin/scripts/generate-style-code.js
+++ b/platform/darwin/scripts/generate-style-code.js
@@ -300,7 +300,17 @@ global.propertyDoc = function (propertyName, property, layerType, kind) {
doc += `\n\nThis attribute corresponds to the <a href="https://www.mapbox.com/mapbox-gl-style-spec/#${anchor}"><code>${property.original}</code></a> layout property in the Mapbox Style Specification.`;
}
doc += '\n\nYou can set this property to an expression containing any of the following:\n\n';
- doc += `* Constant ${describeType(property)} values\n`;
+ doc += `* Constant ${describeType(property)} values`;
+ if ('minimum' in property) {
+ if ('maximum' in property) {
+ doc += ` between ${formatNumber(property.minimum)} and ${formatNumber(property.maximum)} inclusive`;
+ } else {
+ doc += ` no less than ${formatNumber(property.minimum)}`;
+ }
+ } else if ('maximum' in property) {
+ doc += ` no greater than ${formatNumber(property.maximum)}`;
+ }
+ doc += '\n';
if (property.type === 'enum') {
doc += '* Any of the following constant string values:\n';
doc += Object.keys(property.values).map(value => ' * `' + value + '`: ' + property.values[value].doc).join('\n') + '\n';
@@ -393,7 +403,7 @@ global.describeValue = function (value, property, layerType) {
case 'boolean':
return value ? '`YES`' : '`NO`';
case 'number':
- return 'the float `' + value + '`';
+ return 'the float ' + formatNumber(value);
case 'string':
if (value === '') {
return 'the empty string';
@@ -428,7 +438,7 @@ global.describeValue = function (value, property, layerType) {
if (color.r === 1 && color.g === 1 && color.b === 1 && color.a === 1) {
return '`UIColor.whiteColor`';
}
- return 'a `UIColor`' + ` object whose RGB value is ${color.r}, ${color.g}, ${color.b} and whose alpha value is ${color.a}`;
+ return 'a `UIColor`' + ` object whose RGB value is ${formatNumber(color.r)}, ${formatNumber(color.g)}, ${formatNumber(color.b)} and whose alpha value is ${formatNumber(color.a)}`;
case 'array':
let units = property.units || '';
if (units) {
@@ -439,12 +449,12 @@ global.describeValue = function (value, property, layerType) {
if (value[0] === 0 && value[1] === 0 && value[2] === 0 && value[3] === 0) {
return 'an `NSValue` object containing `UIEdgeInsetsZero`';
}
- return 'an `NSValue` object containing a `UIEdgeInsets` struct set to' + ` ${value[0]}${units} on the top, ${value[3]}${units} on the left, ${value[2]}${units} on the bottom, and ${value[1]}${units} on the right`;
+ return 'an `NSValue` object containing a `UIEdgeInsets` struct set to' + ` ${formatNumber(value[0])}${units} on the top, ${formatNumber(value[3])}${units} on the left, ${formatNumber(value[2])}${units} on the bottom, and ${formatNumber(value[1])}${units} on the right`;
case 'offset':
case 'translate':
- return 'an `NSValue` object containing a `CGVector` struct set to' + ` ${value[0]}${units} rightward and ${value[1]}${units} downward`;
+ return 'an `NSValue` object containing a `CGVector` struct set to' + ` ${formatNumber(value[0])}${units} rightward and ${formatNumber(value[1])}${units} downward`;
case 'position':
- return 'an `MGLSphericalPosition` struct set to' + ` ${value[0]} radial, ${value[1]} azimuthal and ${value[2]} polar`;
+ return 'an `MGLSphericalPosition` struct set to' + ` ${formatNumber(value[0])} radial, ${formatNumber(value[1])} azimuthal and ${formatNumber(value[2])} polar`;
default:
return 'the array `' + value.join('`, `') + '`';
}
@@ -453,6 +463,10 @@ global.describeValue = function (value, property, layerType) {
}
};
+global.formatNumber = function (num) {
+ return num.toLocaleString().replace('-', '\u2212');
+}
+
global.propertyDefault = function (property, layerType) {
if (property.name === 'heatmap-color') {
return 'an expression that evaluates to a rainbow color scale from blue to red';
@@ -612,7 +626,7 @@ const layerH = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.h.
const layerM = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.mm.ejs', 'utf8'), { strict: true});
const testLayers = ejs.compile(fs.readFileSync('platform/darwin/test/MGLStyleLayerTests.mm.ejs', 'utf8'), { strict: true});
const forStyleAuthorsMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/For Style Authors.md.ejs', 'utf8'), { strict: true });
-const ddsGuideMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/Using Style Functions at Runtime.md.ejs', 'utf8'), { strict: true });
+const ddsGuideMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/Migrating to Expressions.md.ejs', 'utf8'), { strict: true });
const templatesMD = ejs.compile(fs.readFileSync('platform/darwin/docs/guides/Tile URL Templates.md.ejs', 'utf8'), { strict: true });
const lightH = ejs.compile(fs.readFileSync('platform/darwin/src/MGLLight.h.ejs', 'utf8'), {strict: true});
@@ -650,13 +664,13 @@ function duplicatePlatformDecls(src) {
// Look for a documentation comment that contains “MGLColor” or “UIColor”
// and the subsequent function, method, or property declaration. Try not to
// match greedily.
- return src.replace(/(\/\*\*(?:\*[^\/]|[^*])*?\*\/)(\s*[^;]+?\b(?:MGL|NS|UI)(?:Color|EdgeInsets(?:Zero)?)\b[^;]+?;)/g,
+ return src.replace(/(\/\*\*(?:\*[^\/]|[^*])*?\b(?:MGL|NS|UI)Color\b[\s\S]*?\*\/)(\s*.+?;)/g,
(match, comment, decl) => {
- let macosComment = comment.replace(/\b(?:MGL|UI)(Color|EdgeInsets(?:Zero)?)\b/g, 'NS$1')
+ let macosComment = comment.replace(/\b(?:MGL|UI)Color\b/g, 'NSColor')
// Use the correct indefinite article.
- .replace(/\ba(\s+`?NS(?:Color|EdgeInsets))\b/gi, 'an$1');
- let iosDecl = decl.replace(/\bMGL(Color|EdgeInsets)\b/g, 'UI$1');
- let macosDecl = decl.replace(/\b(?:MGL|UI)(Color|EdgeInsets)\b/g, 'NS$1');
+ .replace(/\ba(\s+`?NSColor)\b/gi, 'an$1');
+ let iosDecl = decl.replace(/\bMGLColor\b/g, 'UIColor');
+ let macosDecl = decl.replace(/\b(?:MGL|UI)Color\b/g, 'NSColor');
return `\
#if TARGET_OS_IPHONE
${comment}${iosDecl}
@@ -743,10 +757,10 @@ writeIfModified(`platform/macos/docs/guides/For Style Authors.md`, forStyleAutho
renamedProperties: renamedPropertiesByLayerType,
layers: layers,
}));
-writeIfModified(`platform/ios/docs/guides/Using Style Functions at Runtime.md`, ddsGuideMD({
+writeIfModified(`platform/ios/docs/guides/Migrating to Expressions.md`, ddsGuideMD({
os: 'iOS',
}));
-writeIfModified(`platform/macos/docs/guides/Using Style Functions at Runtime.md`, ddsGuideMD({
+writeIfModified(`platform/macos/docs/guides/Migrating to Expressions.md`, ddsGuideMD({
os: 'macOS',
}));
writeIfModified(`platform/ios/docs/guides/Tile URL Templates.md`, templatesMD({
diff --git a/platform/darwin/scripts/style-spec-overrides-v8.json b/platform/darwin/scripts/style-spec-overrides-v8.json
index b0c50a06f8..d47b13cdb2 100644
--- a/platform/darwin/scripts/style-spec-overrides-v8.json
+++ b/platform/darwin/scripts/style-spec-overrides-v8.json
@@ -9,28 +9,28 @@
"type": {
"values": {
"fill": {
- "doc": "An `MGLFillStyleLayer` is a style layer that renders one or more filled (and optionally stroked) polygons on the map.\n\nUse a fill style layer to configure the visual appearance of polygon or multipolygon features in vector tiles loaded by an `MGLVectorSource` object or `MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or `MGLMultiPolygonFeature` instances in an `MGLShapeSource` object."
+ "doc": "An `MGLFillStyleLayer` is a style layer that renders one or more filled (and optionally stroked) polygons on the map.\n\nUse a fill style layer to configure the visual appearance of polygon or multipolygon features. These features can come from vector tiles loaded by an `MGLVectorTileSource` object, or they can be `MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or `MGLMultiPolygonFeature` instances in an `MGLShapeSource` or `MGLComputedShapeSource` object."
},
"fill-extrusion": {
- "doc": "An `MGLFillExtrusionStyleLayer` is a style layer that renders one or more 3D extruded polygons on the map.\n\nUse a fill-extrusion style layer to configure the visual appearance of polygon or multipolygon features in vector tiles loaded by an `MGLVectorSource` object or `MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or `MGLMultiPolygonFeature` instances in an `MGLShapeSource` object."
+ "doc": "An `MGLFillExtrusionStyleLayer` is a style layer that renders one or more 3D extruded polygons on the map.\n\nUse a fill-extrusion style layer to configure the visual appearance of polygon or multipolygon features. These features can come from vector tiles loaded by an `MGLVectorTileSource` object, or they can be `MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or `MGLMultiPolygonFeature` instances in an `MGLShapeSource` or `MGLComputedShapeSource` object."
},
"line": {
- "doc": "An `MGLLineStyleLayer` is a style layer that renders one or more stroked polylines on the map.\n\nUse a line style layer to configure the visual appearance of polyline or multipolyline features in vector tiles loaded by an `MGLVectorSource` object or `MGLPolyline`, `MGLPolylineFeature`, `MGLMultiPolyline`, or `MGLMultiPolylineFeature` instances in an `MGLShapeSource` object."
+ "doc": "An `MGLLineStyleLayer` is a style layer that renders one or more stroked polylines on the map.\n\nUse a line style layer to configure the visual appearance of polyline or multipolyline features. These features can come from vector tiles loaded by an `MGLVectorTileSource` object, or they can be `MGLPolyline`, `MGLPolylineFeature`, `MGLMultiPolyline`, or `MGLMultiPolylineFeature` instances in an `MGLShapeSource` or `MGLComputedShapeSource` object."
},
"symbol": {
- "doc": "An `MGLSymbolStyleLayer` is a style layer that renders icon and text labels at points or along lines on the map.\n\nUse a symbol style layer to configure the visual appearance of labels for features in vector tiles loaded by an `MGLVectorSource` object or `MGLShape` or `MGLFeature` instances in an `MGLShapeSource` object."
+ "doc": "An `MGLSymbolStyleLayer` is a style layer that renders icon and text labels at points or along lines on the map.\n\nUse a symbol style layer to configure the visual appearance of feature labels. These features can come from vector tiles loaded by an `MGLVectorTileSource` object, or they can be `MGLShape` or `MGLFeature` instances in an `MGLShapeSource` or `MGLComputedShapeSource` object."
},
"circle": {
- "doc": "An `MGLCircleStyleLayer` is a style layer that renders one or more filled circles on the map.\n\nUse a circle style layer to configure the visual appearance of point or point collection features in vector tiles loaded by an `MGLVectorSource` object or `MGLPointAnnotation`, `MGLPointFeature`, `MGLPointCollection`, or `MGLPointCollectionFeature` instances in an `MGLShapeSource` object.\n\nA circle style layer renders circles whose radii are measured in screen units. To display circles on the map whose radii correspond to real-world distances, use many-sided regular polygons and configure their appearance using an `MGLFillStyleLayer` object."
+ "doc": "An `MGLCircleStyleLayer` is a style layer that renders one or more filled circles on the map.\n\nUse a circle style layer to configure the visual appearance of point or point collection features. These features can come from vector tiles loaded by an `MGLVectorTileSource` object, or they can be `MGLPointAnnotation`, `MGLPointFeature`, `MGLPointCollection`, or `MGLPointCollectionFeature` instances in an `MGLShapeSource` or `MGLComputedShapeSource` object.\n\nA circle style layer renders circles whose radii are measured in screen units. To display circles on the map whose radii correspond to real-world distances, use many-sided regular polygons and configure their appearance using an `MGLFillStyleLayer` object."
},
"heatmap": {
- "doc": "An `MGLHeatmapStyleLayer` is a style layer that renders a <a href=\"https://en.wikipedia.org/wiki/Heat_map\">heatmap</a>.\n\nA heatmap visualizes the spatial distribution of a large, dense set of point data, using color to avoid cluttering the map with individual points at low zoom levels. The points are weighted by an attribute you specify. Use a heatmap style layer in conjunction with point or point collection features in vector tiles loaded by an `MGLVectorSource` object or `MGLPointAnnotation`, `MGLPointFeature`, `MGLPointCollection`, or `MGLPointCollectionFeature` instances in an `MGLShapeSource` object.\n\nConsider accompanying a heatmap style layer with an `MGLCircleStyleLayer` or `MGLSymbolStyleLayer` at high zoom levels. If you are unsure whether the point data in an `MGLShapeSource` is dense enough to warrant a heatmap, you can alternatively cluster the source using the `MGLShapeSourceOptionClustered` option and render the data using an `MGLCircleStyleLayer` or `MGLSymbolStyleLayer`."
+ "doc": "An `MGLHeatmapStyleLayer` is a style layer that renders a <a href=\"https://en.wikipedia.org/wiki/Heat_map\">heatmap</a>.\n\nA heatmap visualizes the spatial distribution of a large, dense set of point data, using color to avoid cluttering the map with individual points at low zoom levels. The points are weighted by an attribute you specify. Use a heatmap style layer in conjunction with point or point collection features. These features can come from vector tiles loaded by an `MGLVectorTileSource` object, or they can be `MGLPointAnnotation`, `MGLPointFeature`, `MGLPointCollection`, or `MGLPointCollectionFeature` instances in an `MGLShapeSource` or `MGLComputedShapeSource` object.\n\nConsider accompanying a heatmap style layer with an `MGLCircleStyleLayer` or `MGLSymbolStyleLayer` at high zoom levels. If you are unsure whether the point data in an `MGLShapeSource` is dense enough to warrant a heatmap, you can alternatively cluster the source using the `MGLShapeSourceOptionClustered` option and render the data using an `MGLCircleStyleLayer` or `MGLSymbolStyleLayer`."
},
"raster": {
- "doc": "An `MGLRasterStyleLayer` is a style layer that renders georeferenced raster imagery on the map, especially raster tiles.\n\nUse a raster style layer to configure the color parameters of raster tiles loaded by an `MGLRasterSource` object or raster images loaded by an `MGLImageSource` object. For example, you could use a raster style layer to render <a href=\"https://www.mapbox.com/satellite/\">Mapbox Satellite</a> imagery, a <a href=\"https://www.mapbox.com/help/define-tileset/#raster-tilesets\">raster tile set</a> uploaded to Mapbox Studio, or a raster map authored in <a href=\"https://tilemill-project.github.io/tilemill/\">TileMill</a>, the classic Mapbox Editor, or Mapbox Studio Classic.\n\nRaster images may also be used as icons or patterns in a style layer. To register an image for use as an icon or pattern, use the `-[MGLStyle setImage:forName:]` method. To configure a point annotation’s image, use the `MGLAnnotationImage` class."
+ "doc": "An `MGLRasterStyleLayer` is a style layer that renders georeferenced raster imagery on the map, especially raster tiles.\n\nUse a raster style layer to configure the color parameters of raster tiles loaded by an `MGLRasterTileSource` object or raster images loaded by an `MGLImageSource` object. For example, you could use a raster style layer to render <a href=\"https://www.mapbox.com/satellite/\">Mapbox Satellite</a> imagery, a <a href=\"https://www.mapbox.com/help/define-tileset/#raster-tilesets\">raster tile set</a> uploaded to Mapbox Studio, or a raster map authored in <a href=\"https://tilemill-project.github.io/tilemill/\">TileMill</a>, the classic Mapbox Editor, or Mapbox Studio Classic.\n\nRaster images may also be used as icons or patterns in a style layer. To register an image for use as an icon or pattern, use the `-[MGLStyle setImage:forName:]` method. To configure a point annotation’s image, use the `MGLAnnotationImage` class."
},
"hillshade": {
- "doc": "An `MGLHillshadeStyleLayer` is a style layer that renders raster <a href=\"https://en.wikipedia.org/wiki/Digital_elevation_model\">digital elevation model</a> (DEM) tiles on the map.\n\nUse a hillshade style layer to configure the color parameters of raster tiles loaded by an `MGLRasterDEMSource` object. For example, you could use a hillshade style layer to render <a href=\"https://www.mapbox.com/help/access-elevation-data/#mapbox-terrain-rgb\">Mapbox Terrain-RGB</a> data.\n\nTo display posterized hillshading based on vector shapes, as with the <a href=\"https://www.mapbox.com/vector-tiles/mapbox-terrain/\">Mapbox Terrain</a> source, use an `MGLVectorSource` object in conjunction with several `MGLFillStyleLayer` objects."
+ "doc": "An `MGLHillshadeStyleLayer` is a style layer that renders raster <a href=\"https://en.wikipedia.org/wiki/Digital_elevation_model\">digital elevation model</a> (DEM) tiles on the map.\n\nUse a hillshade style layer to configure the color parameters of raster tiles loaded by an `MGLRasterDEMSource` object. For example, you could use a hillshade style layer to render <a href=\"https://www.mapbox.com/help/access-elevation-data/#mapbox-terrain-rgb\">Mapbox Terrain-RGB</a> data.\n\nTo display posterized hillshading based on vector shapes, as with the <a href=\"https://www.mapbox.com/vector-tiles/mapbox-terrain/\">Mapbox Terrain</a> source, use an `MGLVectorTileSource` object in conjunction with several `MGLFillStyleLayer` objects."
},
"background": {
"doc": "An `MGLBackgroundStyleLayer` is a style layer that covers the entire map. Use a background style layer to configure a color or pattern to show below all other map content. If the style’s other layers use the Mapbox Streets source, the background style layer is responsible for drawing land, whereas the oceans and other bodies of water are drawn by `MGLFillStyleLayer` objects.\n\nA background style layer is typically the bottommost layer in a style, because it covers the entire map and can occlude any layers below it. You can therefore access it by getting the last item in the `MGLStyle.layers` array.\n\nIf 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."
@@ -46,10 +46,10 @@
"doc": "Offset distance of icon from its anchor."
},
"icon-image": {
- "doc": "Name of image in sprite to use for drawing an image background. Within literal values, attribute names enclosed in curly brackets (e.g. `{token}`) are replaced with the value of the named attribute. Expressions do not support this syntax; for equivalent functionality in expressions, use `stringByAppendingString:` and key path expressions."
+ "doc": "Name of a style image to use for drawing an image background.\n\nUse the `+[MGLStyle setImage:forName:]` method to associate an image with a name that you can set this property to.\n\nWithin a constant string value, a feature attribute name enclosed in curly braces (e.g., `{token}`) is replaced with the value of the named attribute. Tokens inside non-constant expressions are ignored; instead, use `mgl_join:` and key path expressions."
},
"text-field": {
- "doc": "Value to use for a text label. Within literal values, attribute names enclosed in curly brackets (e.g. `{token}`) are replaced with the value of the named attribute. Expressions do not support this syntax; for equivalent functionality in expressions, use `stringByAppendingString:` and key path expressions."
+ "doc": "Value to use for a text label.\n\nWithin a constant string value, a feature attribute name enclosed in curly braces (e.g., `{token}`) is replaced with the value of the named attribute. Tokens inside non-constant expressions are ignored; instead, use `mgl_join:` and key path expressions."
},
"text-font": {
"doc": "An array of font face names used to display the text.\n\nEach font name must be included in the `{fontstack}` portion of the JSON stylesheet’s <a href=\"https://www.mapbox.com/mapbox-gl-style-spec/#glyphs\"><code>glyphs</code></a> property. You can register a custom font when designing the style in Mapbox Studio. Fonts installed on the system are not used.\n\nThe first font named in the array is applied to the text. For each character in the text, if the first font lacks a glyph for the character, the next font is applied as a fallback, and so on."
@@ -84,7 +84,7 @@
},
"paint_heatmap": {
"heatmap-color": {
- "doc": "Defines the color of each pixel based on its density value in a heatmap. Should be an expression that uses `$heatmapDensity` as input."
+ "doc": "The color of each screen point based on its density value in a heatmap. This property is normally set to an interpolation or step expression with the `$heatmapDensity` value as its input."
}
},
"paint_line": {
diff --git a/platform/darwin/src/MGLAbstractShapeSource.h b/platform/darwin/src/MGLAbstractShapeSource.h
deleted file mode 100644
index d61f41fbf6..0000000000
--- a/platform/darwin/src/MGLAbstractShapeSource.h
+++ /dev/null
@@ -1,124 +0,0 @@
-#import "MGLSource.h"
-
-/**
- Options for `MGLShapeSource` objects.
- */
-typedef NSString *MGLShapeSourceOption NS_STRING_ENUM;
-
-/**
- An `NSNumber` object containing a Boolean enabling or disabling clustering.
- If the `shape` property contains point shapes, setting this option to
- `YES` clusters the points by radius into groups. The default value is `NO`.
-
- This attribute corresponds to the
- <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-cluster"><code>cluster</code></a>
- source property in the Mapbox Style Specification.
-
- This option only affects point features within a shape source.
- */
-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 MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius;
-
-/**
- An `NSNumber` object containing an integer; specifies the maximum zoom level at
- which to cluster points if clustering is enabled. Defaults to one zoom level
- less than the value of `MGLShapeSourceOptionMaximumZoomLevel` so that, at the
- maximum zoom level, the shapes are not clustered.
-
- This attribute corresponds to the
- <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 MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering;
-
-/**
- An `NSNumber` object containing an integer; specifies the minimum zoom level at
- which to create vector tiles. The default value is 0.
-
- This attribute corresponds to the
- <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-minzoom"><code>minzoom</code></a>
- source property in the Mapbox Style Specification.
- */
-extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMinimumZoomLevel;
-
-/**
- An `NSNumber` object containing an integer; specifies the maximum zoom level at
- which to create vector tiles. A greater value produces greater detail at high
- zoom levels. The default value is 18.
-
- This attribute corresponds to the
- <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 MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel;
-
-/**
- An `NSNumber` object containing an integer; specifies the size of the tile
- buffer on each side. A value of 0 produces no buffer. A value of 512 produces a
- buffer as wide as the tile itself. Larger values produce fewer rendering
- artifacts near tile edges and slower performance. The default value is 128.
-
- This attribute corresponds to the
- <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 MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionBuffer;
-
-/**
- An `NSNumber` object containing a double; specifies the Douglas-Peucker
- simplification tolerance. A greater value produces simpler geometries and
- improves performance. The default value is 0.375.
-
- This attribute corresponds to the
- <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 MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
-
-/**
- An `NSNumber` object containing a Boolean value; specifies whether the shape of
- an `MGLComputedShapeSource` should be wrapped to accomodate coordinates with
- longitudes beyond −180 and 180. The default value is `NO`.
-
- Setting this option to `YES` affects rendering performance.
-
- This option is ignored when creating an instance of a class besides
- `MGLComputedShapeSource`.
- */
-extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionWrapsCoordinates;
-
-/**
- An `NSNumber` object containing a Boolean value; specifies whether the shape of
- an `MGLComputedShapeSource` should be clipped at the edge of each tile. The
- default value is `NO`.
-
- Setting this option to `YES` affects rendering performance. Use this option to
- clip `MGLPolyline`s and `MGLPolygon`s at tile boundaries without artifacts.
-
- This option is ignored when creating an instance of a class besides
- `MGLComputedShapeSource`.
- */
-extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionClipsCoordinates;
-
-/**
- `MGLAbstractShapeSource` is an abstract base class for map content sources that
- supply vector shapes to be shown on the map. A shape source is added to an
- `MGLStyle` object along with an `MGLVectorStyleLayer` object. The vector style
- layer defines the appearance of any content supplied by the shape source.
-
-
- Do not create instances of this class directly, and do not create your own
- subclasses of this class. Instead, create instances of `MGLShapeSource` or
- `MGLComputedShapeSource`.
- */
-MGL_EXPORT
-@interface MGLAbstractShapeSource : MGLSource
-
-
-@end
diff --git a/platform/darwin/src/MGLAbstractShapeSource.mm b/platform/darwin/src/MGLAbstractShapeSource.mm
deleted file mode 100644
index eb0807cee0..0000000000
--- a/platform/darwin/src/MGLAbstractShapeSource.mm
+++ /dev/null
@@ -1,136 +0,0 @@
-#import "MGLAbstractShapeSource.h"
-#import "MGLAbstractShapeSource_Private.h"
-
-const MGLShapeSourceOption MGLShapeSourceOptionBuffer = @"MGLShapeSourceOptionBuffer";
-const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius = @"MGLShapeSourceOptionClusterRadius";
-const MGLShapeSourceOption MGLShapeSourceOptionClustered = @"MGLShapeSourceOptionClustered";
-const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel = @"MGLShapeSourceOptionMaximumZoomLevel";
-const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering = @"MGLShapeSourceOptionMaximumZoomLevelForClustering";
-const MGLShapeSourceOption MGLShapeSourceOptionMinimumZoomLevel = @"MGLShapeSourceOptionMinimumZoomLevel";
-const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLShapeSourceOptionSimplificationTolerance";
-const MGLShapeSourceOption MGLShapeSourceOptionWrapsCoordinates = @"MGLShapeSourceOptionWrapsCoordinates";
-const MGLShapeSourceOption MGLShapeSourceOptionClipsCoordinates = @"MGLShapeSourceOptionClipsCoordinates";
-
-@interface MGLAbstractShapeSource ()
-
-@end
-
-@implementation MGLAbstractShapeSource
-
-@end
-
-mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options) {
- auto geoJSONOptions = mbgl::style::GeoJSONOptions();
-
- if (NSNumber *value = options[MGLShapeSourceOptionMinimumZoomLevel]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionMaximumZoomLevel must be an NSNumber."];
- }
- geoJSONOptions.minzoom = value.integerValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevel]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionMaximumZoomLevel must be an NSNumber."];
- }
- geoJSONOptions.maxzoom = value.integerValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionBuffer]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionBuffer must be an NSNumber."];
- }
- geoJSONOptions.buffer = value.integerValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionSimplificationTolerance]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionSimplificationTolerance must be an NSNumber."];
- }
- geoJSONOptions.tolerance = value.doubleValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionClusterRadius]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionClusterRadius must be an NSNumber."];
- }
- geoJSONOptions.clusterRadius = value.integerValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevelForClustering]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionMaximumZoomLevelForClustering must be an NSNumber."];
- }
- geoJSONOptions.clusterMaxZoom = value.integerValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionClustered]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionClustered must be an NSNumber."];
- }
- geoJSONOptions.cluster = value.boolValue;
- }
-
- return geoJSONOptions;
-}
-
-mbgl::style::CustomGeometrySource::Options MBGLCustomGeometrySourceOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options) {
- mbgl::style::CustomGeometrySource::Options sourceOptions;
-
- if (NSNumber *value = options[MGLShapeSourceOptionMinimumZoomLevel]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionMaximumZoomLevelForClustering must be an NSNumber."];
- }
- sourceOptions.zoomRange.min = value.integerValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevel]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionMaximumZoomLevel must be an NSNumber."];
- }
- sourceOptions.zoomRange.max = value.integerValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionBuffer]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionBuffer must be an NSNumber."];
- }
- sourceOptions.tileOptions.buffer = value.integerValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionSimplificationTolerance]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionSimplificationTolerance must be an NSNumber."];
- }
- sourceOptions.tileOptions.tolerance = value.doubleValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionWrapsCoordinates]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionWrapsCoordinates must be an NSNumber."];
- }
- sourceOptions.tileOptions.wrap = value.boolValue;
- }
-
- if (NSNumber *value = options[MGLShapeSourceOptionClipsCoordinates]) {
- if (![value isKindOfClass:[NSNumber class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"MGLShapeSourceOptionClipsCoordinates must be an NSNumber."];
- }
- sourceOptions.tileOptions.clip = value.boolValue;
- }
-
- return sourceOptions;
-}
diff --git a/platform/darwin/src/MGLAccountManager.h b/platform/darwin/src/MGLAccountManager.h
index 741cc323cb..436e45ca9b 100644
--- a/platform/darwin/src/MGLAccountManager.h
+++ b/platform/darwin/src/MGLAccountManager.h
@@ -5,7 +5,7 @@
NS_ASSUME_NONNULL_BEGIN
/**
- The MGLAccountManager object provides a global way to set a Mapbox API access
+ The `MGLAccountManager` object provides a global way to set a Mapbox API access
token.
*/
MGL_EXPORT
@@ -14,9 +14,9 @@ MGL_EXPORT
#pragma mark Authorizing Access
/**
- Set the
+ The
<a href="https://www.mapbox.com/help/define-access-token/">Mapbox access token</a>
- to be used by all instances of MGLMapView in the current application.
+ used by all instances of `MGLMapView` in the current application.
Mapbox-hosted vector tiles and styles require an API access token, which you
can obtain from the
@@ -25,26 +25,18 @@ MGL_EXPORT
your Mapbox account. They also deter other developers from using your styles
without your permission.
- @param accessToken A Mapbox access token. Calling this method with a value of
- `nil` has no effect.
+ Setting this property to a value of `nil` has no effect.
@note You must set the access token before attempting to load any Mapbox-hosted
style. Therefore, you should generally set it before creating an instance of
- MGLMapView. The recommended way to set an access token is to add an entry to
- your application’s Info.plist file with the key `MGLMapboxAccessToken` and
- the type String. Alternatively, you may call this method from your
+ `MGLMapView`. The recommended way to set an access token is to add an entry
+ to your application’s Info.plist file with the key `MGLMapboxAccessToken`
+ and the type `String`. Alternatively, you may call this method from your
application delegate’s `-applicationDidFinishLaunching:` method.
*/
-+ (void)setAccessToken:(nullable NSString *)accessToken;
+@property (class, nullable) NSString *accessToken;
-/**
- Returns the
- <a href="https://www.mapbox.com/help/define-access-token/">Mapbox access token</a>
- in use by instances of MGLMapView in the current application.
- */
-+ (nullable NSString *)accessToken;
-
-+ (BOOL)mapboxMetricsEnabledSettingShownInApp __attribute__((deprecated("Telemetry settings are now always shown in the ℹ️ menu.")));
++ (BOOL)mapboxMetricsEnabledSettingShownInApp __attribute__((unavailable("Telemetry settings are now always shown in the ℹ️ menu.")));
@end
diff --git a/platform/darwin/src/MGLAccountManager.m b/platform/darwin/src/MGLAccountManager.m
index 729caeaa31..73da8ddd63 100644
--- a/platform/darwin/src/MGLAccountManager.m
+++ b/platform/darwin/src/MGLAccountManager.m
@@ -54,11 +54,6 @@
return _sharedManager;
}
-+ (BOOL)mapboxMetricsEnabledSettingShownInApp {
- NSLog(@"mapboxMetricsEnabledSettingShownInApp is no longer necessary; the Mapbox Maps SDK for iOS has changed to always provide a telemetry setting in-app.");
- return YES;
-}
-
+ (void)setAccessToken:(NSString *)accessToken {
accessToken = [accessToken stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceAndNewlineCharacterSet]];
@@ -69,9 +64,7 @@
[MGLAccountManager sharedManager].accessToken = accessToken;
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
- // Update MGLMapboxEvents
- // NOTE: This is (likely) the initial setup of MGLMapboxEvents
- [MGLMapboxEvents sharedManager];
+ [MGLMapboxEvents setupWithAccessToken:accessToken];
#endif
}
diff --git a/platform/darwin/src/MGLAccountManager_Private.h b/platform/darwin/src/MGLAccountManager_Private.h
index 655af08f20..b68016b1a7 100644
--- a/platform/darwin/src/MGLAccountManager_Private.h
+++ b/platform/darwin/src/MGLAccountManager_Private.h
@@ -3,7 +3,7 @@
@interface MGLAccountManager (Private)
/// Returns the shared instance of the `MGLAccountManager` class.
-+ (instancetype)sharedManager;
+@property (class, nonatomic, readonly) MGLAccountManager *sharedManager;
/// The current global access token.
@property (atomic) NSString *accessToken;
diff --git a/platform/darwin/src/MGLAttributionInfo.mm b/platform/darwin/src/MGLAttributionInfo.mm
index 73147270c1..07d10e852b 100644
--- a/platform/darwin/src/MGLAttributionInfo.mm
+++ b/platform/darwin/src/MGLAttributionInfo.mm
@@ -49,7 +49,12 @@
CGFloat blue;
CGFloat alpha;
#if !TARGET_OS_IPHONE
- linkColor = [linkColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+ // CSS uses the sRGB color space.
+ if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) {
+ linkColor = [linkColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+ } else {
+ linkColor = [linkColor colorUsingColorSpace:[NSColorSpace sRGBColorSpace]];
+ }
#endif
[linkColor getRed:&red green:&green blue:&blue alpha:&alpha];
[css appendFormat:
diff --git a/platform/darwin/src/MGLBackgroundStyleLayer.h b/platform/darwin/src/MGLBackgroundStyleLayer.h
index 9d2673c859..d5c3ed5403 100644
--- a/platform/darwin/src/MGLBackgroundStyleLayer.h
+++ b/platform/darwin/src/MGLBackgroundStyleLayer.h
@@ -37,6 +37,7 @@ which it is added.
#pragma mark - Accessing the Paint Attributes
+#if TARGET_OS_IPHONE
/**
The color with which the background will be drawn.
@@ -59,6 +60,30 @@ which it is added.
feature attributes.
*/
@property (nonatomic, null_resettable) NSExpression *backgroundColor;
+#else
+/**
+ The color with which the background will be drawn.
+
+ The default value of this property is an expression that evaluates to
+ `NSColor.blackColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ This property is only applied to the style if `backgroundPattern` is set to
+ `nil`. Otherwise, it is ignored.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable
+
+ This property does not support applying interpolation or step functions to
+ feature attributes.
+ */
+@property (nonatomic, null_resettable) NSExpression *backgroundColor;
+#endif
/**
The transition affecting any changes to this layer’s `backgroundColor` property.
@@ -71,11 +96,11 @@ which it is added.
The opacity at which the background will be drawn.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
diff --git a/platform/darwin/src/MGLBackgroundStyleLayer.mm b/platform/darwin/src/MGLBackgroundStyleLayer.mm
index 7c4cf79709..993645d3a8 100644
--- a/platform/darwin/src/MGLBackgroundStyleLayer.mm
+++ b/platform/darwin/src/MGLBackgroundStyleLayer.mm
@@ -116,7 +116,8 @@
if (propertyValue.isUndefined()) {
propertyValue = self.rawLayer->getDefaultBackgroundPattern();
}
- return MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ NSExpression *expression = MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ return expression.mgl_expressionByReplacingTokensWithKeyPaths;
}
- (void)setBackgroundPatternTransition:(MGLTransition )transition {
diff --git a/platform/darwin/src/MGLCircleStyleLayer.h b/platform/darwin/src/MGLCircleStyleLayer.h
index caa6d2f6cb..06b4de32f0 100644
--- a/platform/darwin/src/MGLCircleStyleLayer.h
+++ b/platform/darwin/src/MGLCircleStyleLayer.h
@@ -62,9 +62,10 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
circles on the map.
Use a circle style layer to configure the visual appearance of point or point
- collection features in vector tiles loaded by an `MGLVectorSource` object or
- `MGLPointAnnotation`, `MGLPointFeature`, `MGLPointCollection`, or
- `MGLPointCollectionFeature` instances in an `MGLShapeSource` object.
+ collection features. These features can come from vector tiles loaded by an
+ `MGLVectorTileSource` object, or they can be `MGLPointAnnotation`,
+ `MGLPointFeature`, `MGLPointCollection`, or `MGLPointCollectionFeature`
+ instances in an `MGLShapeSource` or `MGLComputedShapeSource` object.
A circle style layer renders circles whose radii are measured in screen units.
To display circles on the map whose radii correspond to real-world distances,
@@ -83,7 +84,7 @@ typedef NS_ENUM(NSUInteger, MGLCircleTranslationAnchor) {
let layer = MGLCircleStyleLayer(identifier: "circles", source: population)
layer.sourceLayerIdentifier = "population"
layer.circleColor = NSExpression(forConstantValue: UIColor.green)
- layer.circleRadius = NSExpression(format: "FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'exponential', 1.75, %@)",
+ layer.circleRadius = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'exponential', 1.75, %@)",
[12: 2,
22: 180])
layer.circleOpacity = NSExpression(forConstantValue: 0.7)
@@ -116,7 +117,7 @@ MGL_EXPORT
full opacity.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
@@ -136,6 +137,7 @@ MGL_EXPORT
*/
@property (nonatomic) MGLTransition circleBlurTransition;
+#if TARGET_OS_IPHONE
/**
The fill color of the circle.
@@ -153,6 +155,25 @@ MGL_EXPORT
feature attributes
*/
@property (nonatomic, null_resettable) NSExpression *circleColor;
+#else
+/**
+ The fill color of the circle.
+
+ The default value of this property is an expression that evaluates to
+ `NSColor.blackColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable and/or
+ feature attributes
+ */
+@property (nonatomic, null_resettable) NSExpression *circleColor;
+#endif
/**
The transition affecting any changes to this layer’s `circleColor` property.
@@ -165,11 +186,11 @@ MGL_EXPORT
The opacity at which the circle will be drawn.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -214,11 +235,11 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `5`. Set this property to `nil` to reset it to the default value.
+ 5. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -264,6 +285,7 @@ MGL_EXPORT
@property (nonatomic, null_resettable) NSExpression *circlePitchScale __attribute__((unavailable("Use circleScaleAlignment instead.")));
+#if TARGET_OS_IPHONE
/**
The stroke color of the circle.
@@ -281,6 +303,25 @@ MGL_EXPORT
feature attributes
*/
@property (nonatomic, null_resettable) NSExpression *circleStrokeColor;
+#else
+/**
+ The stroke color of the circle.
+
+ The default value of this property is an expression that evaluates to
+ `NSColor.blackColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable and/or
+ feature attributes
+ */
+@property (nonatomic, null_resettable) NSExpression *circleStrokeColor;
+#endif
/**
The transition affecting any changes to this layer’s `circleStrokeColor` property.
@@ -293,11 +334,11 @@ MGL_EXPORT
The opacity of the circle's stroke.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -320,11 +361,11 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
diff --git a/platform/darwin/src/MGLComputedShapeSource.h b/platform/darwin/src/MGLComputedShapeSource.h
index f90f2c94b1..068c49245c 100644
--- a/platform/darwin/src/MGLComputedShapeSource.h
+++ b/platform/darwin/src/MGLComputedShapeSource.h
@@ -1,15 +1,38 @@
-#import "MGLAbstractShapeSource.h"
-
#import "MGLFoundation.h"
#import "MGLGeometry.h"
#import "MGLTypes.h"
-#import "MGLShape.h"
+#import "MGLShapeSource.h"
NS_ASSUME_NONNULL_BEGIN
@protocol MGLFeature;
/**
+ An `NSNumber` object containing a Boolean value; specifies whether the shape of
+ an `MGLComputedShapeSource` should be wrapped to accomodate coordinates with
+ longitudes beyond −180 and 180. The default value is `NO`.
+
+ Setting this option to `YES` affects rendering performance.
+
+ This option is used with the `MGLComputedShapeSource` class; it is ignored when
+ creating an `MGLShapeSource` object.
+ */
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionWrapsCoordinates;
+
+/**
+ An `NSNumber` object containing a Boolean value; specifies whether the shape of
+ an `MGLComputedShapeSource` should be clipped at the edge of each tile. The
+ default value is `NO`.
+
+ Setting this option to `YES` affects rendering performance. Use this option to
+ clip `MGLPolyline`s and `MGLPolygon`s at tile boundaries without artifacts.
+
+ This option is used with the `MGLComputedShapeSource` class; it is ignored when
+ creating an `MGLShapeSource` object.
+ */
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionClipsCoordinates;
+
+/**
Data source for `MGLComputedShapeSource`. This protocol defines two optional methods for fetching
data, one based on tile coordinates, and one based on a bounding box. Classes that implement this
protocol must implement one, and only one of the methods. Methods on this protocol will not be
@@ -38,21 +61,42 @@ NS_ASSUME_NONNULL_BEGIN
@end
/**
- A source for vector data that is fetched one tile at a time. Useful for sources that are
- too large to fit in memory, or are already divided into tiles, but not in Mapbox Vector Tile format.
+ `MGLComputedShapeSource` is a map content source that supplies vector shapes,
+ one tile at a time, to be shown on the map on demand. You implement a class
+ conforming to the `MGLComputedShapeSourceDataSource` protocol that returns
+ instances of `MGLShape` or `MGLFeature`, then add a computed shape source to an
+ `MGLStyle` object along with an `MGLVectorStyleLayer` object. The vector style
+ layer defines the appearance of any content supplied by the computed shape
+ source.
- Supported options are `MGLShapeSourceOptionMinimumZoomLevel`, `MGLShapeSourceOptionMaximumZoomLevel`,
- `MGLShapeSourceOptionBuffer`, and `MGLShapeSourceOptionSimplificationTolerance.` This source does
- not support clustering.
+ `MGLComputedShapeSource` is similar to `MGLShapeSource` but is optimized for
+ data sets that change dynamically or are too large to fit completely in memory.
+ It is also useful for data that is divided into tiles in a format other than
+ <a href="https://www.mapbox.com/vector-tiles/">Mapbox Vector Tiles</a>. For
+ <a href="http://geojson.org/">GeoJSON</a> data, use the `MGLShapeSource` class.
+ For static tiles or Mapbox Vector Tiles, use the `MGLVectorTileSource` class.
+
+ You can add and remove sources dynamically using methods such as
+ `-[MGLStyle addSource:]` and `-[MGLStyle sourceWithIdentifier:]`. This class
+ cannot be represented in a style JSON file; you must add it ot the style at
+ runtime.
*/
MGL_EXPORT
-@interface MGLComputedShapeSource : MGLAbstractShapeSource
+@interface MGLComputedShapeSource : MGLSource
/**
Returns a custom shape data source initialized with an identifier, and a
dictionary of options for the source according to the
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson">style
specification</a>.
+
+ This class supports the following options:
+ `MGLShapeSourceOptionMinimumZoomLevel`, `MGLShapeSourceOptionMaximumZoomLevel`,
+ `MGLShapeSourceOptionBuffer`,
+ `MGLShapeSourceOptionSimplificationTolerance`,
+ `MGLShapeSourceOptionWrapsCoordinates`, and
+ `MGLShapeSourceOptionClipsCoordinates`. Shapes provided by a computed
+ shape source cannot be clustered.
@param identifier A string that uniquely identifies the source.
@param options An `NSDictionary` of options for this source.
@@ -64,6 +108,14 @@ MGL_EXPORT
dictionary of options for the source according to the
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson">style
specification</a>.
+
+ This class supports the following options:
+ `MGLShapeSourceOptionMinimumZoomLevel`, `MGLShapeSourceOptionMaximumZoomLevel`,
+ `MGLShapeSourceOptionBuffer`,
+ `MGLShapeSourceOptionSimplificationTolerance`,
+ `MGLShapeSourceOptionWrapsCoordinates`, and
+ `MGLShapeSourceOptionClipsCoordinates`. Shapes provided by a computed shape
+ source cannot be clustered.
@param identifier A string that uniquely identifies the source.
@param options An `NSDictionary` of options for this source.
diff --git a/platform/darwin/src/MGLComputedShapeSource.mm b/platform/darwin/src/MGLComputedShapeSource.mm
index 0a3c92bb97..fb25eb8eb4 100644
--- a/platform/darwin/src/MGLComputedShapeSource.mm
+++ b/platform/darwin/src/MGLComputedShapeSource.mm
@@ -1,9 +1,8 @@
-#import "MGLComputedShapeSource.h"
+#import "MGLComputedShapeSource_Private.h"
#import "MGLMapView_Private.h"
#import "MGLSource_Private.h"
#import "MGLShape_Private.h"
-#import "MGLAbstractShapeSource_Private.h"
#import "MGLGeometry_Private.h"
#include <mbgl/map/map.hpp>
@@ -11,6 +10,63 @@
#include <mbgl/tile/tile_id.hpp>
#include <mbgl/util/geojson.hpp>
+const MGLShapeSourceOption MGLShapeSourceOptionWrapsCoordinates = @"MGLShapeSourceOptionWrapsCoordinates";
+const MGLShapeSourceOption MGLShapeSourceOptionClipsCoordinates = @"MGLShapeSourceOptionClipsCoordinates";
+
+mbgl::style::CustomGeometrySource::Options MBGLCustomGeometrySourceOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options) {
+ mbgl::style::CustomGeometrySource::Options sourceOptions;
+
+ if (NSNumber *value = options[MGLShapeSourceOptionMinimumZoomLevel]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionMaximumZoomLevelForClustering must be an NSNumber."];
+ }
+ sourceOptions.zoomRange.min = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevel]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionMaximumZoomLevel must be an NSNumber."];
+ }
+ sourceOptions.zoomRange.max = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionBuffer]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionBuffer must be an NSNumber."];
+ }
+ sourceOptions.tileOptions.buffer = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionSimplificationTolerance]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionSimplificationTolerance must be an NSNumber."];
+ }
+ sourceOptions.tileOptions.tolerance = value.doubleValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionWrapsCoordinates]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionWrapsCoordinates must be an NSNumber."];
+ }
+ sourceOptions.tileOptions.wrap = value.boolValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionClipsCoordinates]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionClipsCoordinates must be an NSNumber."];
+ }
+ sourceOptions.tileOptions.clip = value.boolValue;
+ }
+
+ return sourceOptions;
+}
+
@interface MGLComputedShapeSource () {
std::unique_ptr<mbgl::style::CustomGeometrySource> _pendingSource;
}
diff --git a/platform/darwin/src/MGLAbstractShapeSource_Private.h b/platform/darwin/src/MGLComputedShapeSource_Private.h
index ddde55b149..e1887caf8d 100644
--- a/platform/darwin/src/MGLAbstractShapeSource_Private.h
+++ b/platform/darwin/src/MGLComputedShapeSource_Private.h
@@ -1,22 +1,12 @@
-#import "MGLAbstractShapeSource.h"
-
#import "MGLFoundation.h"
#import "MGLTypes.h"
-#import "MGLShape.h"
+#import "MGLComputedShapeSource.h"
-#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/style/sources/custom_geometry_source.hpp>
NS_ASSUME_NONNULL_BEGIN
-@interface MGLAbstractShapeSource (Private)
-
-MGL_EXPORT
-
-mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options);
-
MGL_EXPORT
mbgl::style::CustomGeometrySource::Options MBGLCustomGeometrySourceOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options);
-@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLFeature.h b/platform/darwin/src/MGLFeature.h
index a13821cf96..d0c9e26062 100644
--- a/platform/darwin/src/MGLFeature.h
+++ b/platform/darwin/src/MGLFeature.h
@@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
The `MGLFeature` protocol is used to provide details about geographic features
- contained in an `MGLShapeSource` or `MGLVectorSource` object. Each concrete
+ contained in an `MGLShapeSource` or `MGLVectorTileSource` object. Each concrete
subclass of `MGLShape` in turn has a subclass that conforms to this protocol. A
feature object associates a shape with an optional identifier and attributes.
@@ -23,8 +23,8 @@ NS_ASSUME_NONNULL_BEGIN
In addition to adding data to the map, you can also extract data from the map:
`-[MGLMapView visibleFeaturesAtPoint:]` and related methods return feature
objects that correspond to features in the source. This enables you to inspect
- the properties of features in vector tiles loaded by `MGLVectorSource` objects.
- You also reuse these feature objects as overlay annotations.
+ the properties of features in vector tiles loaded by `MGLVectorTileSource`
+ objects. You also reuse these feature objects as overlay annotations.
While it is possible to add `MGLFeature`-conforming objects to the map as
annotations using `-[MGLMapView addAnnotations:]` and related methods, doing so
@@ -43,12 +43,12 @@ NS_ASSUME_NONNULL_BEGIN
source.
You can configure an `MGLVectorStyleLayer` object to include or exclude a
- specific feature in an `MGLShapeSource` or `MGLVectorSource`. In the
+ specific feature in an `MGLShapeSource` or `MGLVectorTileSource`. In the
`MGLVectorStyleLayer.predicate` property, compare the special `$id` attribute
to the feature’s identifier.
- In vector tiles loaded by `MGLVectorSource` objects, the identifier corresponds
- to the
+ In vector tiles loaded by `MGLVectorTileSource` objects, the identifier
+ corresponds to the
<a href="https://github.com/mapbox/vector-tile-spec/tree/master/2.1#42-features">feature identifier</a>
(`id`). If the source does not specify the feature’s identifier, the value of
this property is `nil`. If specified, the identifier may be an integer,
@@ -83,7 +83,7 @@ NS_ASSUME_NONNULL_BEGIN
A dictionary of attributes for this feature.
You can configure an `MGLVectorStyleLayer` object to include or exclude a
- specific feature in an `MGLShapeSource` or `MGLVectorSource`. In the
+ specific feature in an `MGLShapeSource` or `MGLVectorTileSource`. In the
`MGLVectorStyleLayer.predicate` property, compare a key of the attribute
dictionary to the value you want to include. For example, if you want an
`MGLLineStyleLayer` object to display only important features, you might assign
@@ -107,7 +107,7 @@ NS_ASSUME_NONNULL_BEGIN
`MGLSymbolStyleLayer.textField` to an `MGLStyleValue` object containing the
raw string value `{name}`.
- In vector tiles loaded by `MGLVectorSource` objects, the keys and values of
+ In vector tiles loaded by `MGLVectorTileSource` objects, the keys and values of
each feature’s attribute dictionary are determined by the source. Each
attribute name is a string, while each attribute value may be a null value,
Boolean value, integer, floating-point number, or string. These data types are
@@ -238,11 +238,12 @@ MGL_EXPORT
An `MGLShapeCollectionFeature` object associates a shape collection with an
optional identifier and attributes.
- `MGLShapeCollectionFeature` is most commonly used to add multiple shapes to a single
- `MGLShapeSource`. Configure the appearance of an `MGLSource`’s shape collection
- collectively using an `MGLSymbolStyleLayer` object, or use multiple instances of
- `MGLCircleStyleLayer`, `MGLFillStyleLayer`, and `MGLLineStyleLayer` to
- configure the appearance of each kind of shape inside the collection.
+ `MGLShapeCollectionFeature` is most commonly used to add multiple shapes to a
+ single `MGLShapeSource`. Configure the appearance of an `MGLSource`’s shape
+ collection collectively using an `MGLSymbolStyleLayer` object, or use multiple
+ instances of `MGLCircleStyleLayer`, `MGLFillStyleLayer`, and
+ `MGLLineStyleLayer` to configure the appearance of each kind of shape inside
+ the collection.
A shape collection feature is known as a
<a href="https://tools.ietf.org/html/rfc7946#section-3.3">feature collection</a>
diff --git a/platform/darwin/src/MGLFillExtrusionStyleLayer.h b/platform/darwin/src/MGLFillExtrusionStyleLayer.h
index d1d5af6ba2..7c3a0773e4 100644
--- a/platform/darwin/src/MGLFillExtrusionStyleLayer.h
+++ b/platform/darwin/src/MGLFillExtrusionStyleLayer.h
@@ -29,9 +29,10 @@ typedef NS_ENUM(NSUInteger, MGLFillExtrusionTranslationAnchor) {
extruded polygons on the map.
Use a fill-extrusion style layer to configure the visual appearance of polygon
- or multipolygon features in vector tiles loaded by an `MGLVectorSource` object
- or `MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or
- `MGLMultiPolygonFeature` instances in an `MGLShapeSource` object.
+ or multipolygon features. These features can come from vector tiles loaded by
+ an `MGLVectorTileSource` object, or they can be `MGLPolygon`,
+ `MGLPolygonFeature`, `MGLMultiPolygon`, or `MGLMultiPolygonFeature` instances
+ in an `MGLShapeSource` or `MGLComputedShapeSource` object.
You can access an existing fill-extrusion style layer using the
`-[MGLStyle layerWithIdentifier:]` method if you know its identifier;
@@ -77,14 +78,14 @@ MGL_EXPORT
This property is measured in meters.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `fillExtrusionHeight` is
non-`nil`. Otherwise, it is ignored.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -100,6 +101,7 @@ MGL_EXPORT
*/
@property (nonatomic) MGLTransition fillExtrusionBaseTransition;
+#if TARGET_OS_IPHONE
/**
The base color of this layer. The extrusion's surfaces will be shaded
differently based on this color in combination with the `light` settings. If
@@ -123,6 +125,31 @@ MGL_EXPORT
feature attributes
*/
@property (nonatomic, null_resettable) NSExpression *fillExtrusionColor;
+#else
+/**
+ The base color of this layer. The extrusion's surfaces will be shaded
+ differently based on this color in combination with the `light` settings. If
+ this color is specified with an alpha component, the alpha component will be
+ ignored; use `fillExtrusionOpacity` to set layer opacityco.
+
+ The default value of this property is an expression that evaluates to
+ `NSColor.blackColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ This property is only applied to the style if `fillExtrusionPattern` is set to
+ `nil`. Otherwise, it is ignored.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable and/or
+ feature attributes
+ */
+@property (nonatomic, null_resettable) NSExpression *fillExtrusionColor;
+#endif
/**
The transition affecting any changes to this layer’s `fillExtrusionColor` property.
@@ -137,11 +164,11 @@ MGL_EXPORT
This property is measured in meters.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -162,11 +189,11 @@ MGL_EXPORT
per-layer, not per-feature, basis, and data-driven styling is not available.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
diff --git a/platform/darwin/src/MGLFillExtrusionStyleLayer.mm b/platform/darwin/src/MGLFillExtrusionStyleLayer.mm
index 1baa264689..688ce4c1ac 100644
--- a/platform/darwin/src/MGLFillExtrusionStyleLayer.mm
+++ b/platform/darwin/src/MGLFillExtrusionStyleLayer.mm
@@ -231,7 +231,8 @@ namespace mbgl {
if (propertyValue.isUndefined()) {
propertyValue = self.rawLayer->getDefaultFillExtrusionPattern();
}
- return MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ NSExpression *expression = MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ return expression.mgl_expressionByReplacingTokensWithKeyPaths;
}
- (void)setFillExtrusionPatternTransition:(MGLTransition )transition {
diff --git a/platform/darwin/src/MGLFillStyleLayer.h b/platform/darwin/src/MGLFillStyleLayer.h
index 5caab91b45..a159a924e6 100644
--- a/platform/darwin/src/MGLFillStyleLayer.h
+++ b/platform/darwin/src/MGLFillStyleLayer.h
@@ -28,9 +28,10 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslationAnchor) {
optionally stroked) polygons on the map.
Use a fill style layer to configure the visual appearance of polygon or
- multipolygon features in vector tiles loaded by an `MGLVectorSource` object or
- `MGLPolygon`, `MGLPolygonFeature`, `MGLMultiPolygon`, or
- `MGLMultiPolygonFeature` instances in an `MGLShapeSource` object.
+ multipolygon features. These features can come from vector tiles loaded by an
+ `MGLVectorTileSource` object, or they can be `MGLPolygon`, `MGLPolygonFeature`,
+ `MGLMultiPolygon`, or `MGLMultiPolygonFeature` instances in an `MGLShapeSource`
+ or `MGLComputedShapeSource` object.
You can access an existing fill style layer using the
`-[MGLStyle layerWithIdentifier:]` method if you know its identifier;
@@ -94,6 +95,7 @@ MGL_EXPORT
@property (nonatomic, null_resettable) NSExpression *fillAntialias __attribute__((unavailable("Use fillAntialiased instead.")));
+#if TARGET_OS_IPHONE
/**
The color of the filled part of this layer.
@@ -114,6 +116,28 @@ MGL_EXPORT
feature attributes
*/
@property (nonatomic, null_resettable) NSExpression *fillColor;
+#else
+/**
+ The color of the filled part of this layer.
+
+ The default value of this property is an expression that evaluates to
+ `NSColor.blackColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ This property is only applied to the style if `fillPattern` is set to `nil`.
+ Otherwise, it is ignored.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable and/or
+ feature attributes
+ */
+@property (nonatomic, null_resettable) NSExpression *fillColor;
+#endif
/**
The transition affecting any changes to this layer’s `fillColor` property.
@@ -127,11 +151,11 @@ MGL_EXPORT
value will also affect the 1pt stroke around the fill, if the stroke is used.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -147,6 +171,7 @@ MGL_EXPORT
*/
@property (nonatomic) MGLTransition fillOpacityTransition;
+#if TARGET_OS_IPHONE
/**
The outline color of the fill. Matches the value of `fillColor` if unspecified.
@@ -164,6 +189,25 @@ MGL_EXPORT
feature attributes
*/
@property (nonatomic, null_resettable) NSExpression *fillOutlineColor;
+#else
+/**
+ The outline color of the fill. Matches the value of `fillColor` if unspecified.
+
+ This property is only applied to the style if `fillPattern` is set to `nil`,
+ and `fillAntialiased` is set to an expression that evaluates to `YES`.
+ Otherwise, it is ignored.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable and/or
+ feature attributes
+ */
+@property (nonatomic, null_resettable) NSExpression *fillOutlineColor;
+#endif
/**
The transition affecting any changes to this layer’s `fillOutlineColor` property.
diff --git a/platform/darwin/src/MGLFillStyleLayer.mm b/platform/darwin/src/MGLFillStyleLayer.mm
index ab28b414b5..c975e28d6b 100644
--- a/platform/darwin/src/MGLFillStyleLayer.mm
+++ b/platform/darwin/src/MGLFillStyleLayer.mm
@@ -220,7 +220,8 @@ namespace mbgl {
if (propertyValue.isUndefined()) {
propertyValue = self.rawLayer->getDefaultFillPattern();
}
- return MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ NSExpression *expression = MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ return expression.mgl_expressionByReplacingTokensWithKeyPaths;
}
- (void)setFillPatternTransition:(MGLTransition )transition {
diff --git a/platform/darwin/src/MGLGeometry.h b/platform/darwin/src/MGLGeometry.h
index 7c68033abf..a8d3759106 100644
--- a/platform/darwin/src/MGLGeometry.h
+++ b/platform/darwin/src/MGLGeometry.h
@@ -14,6 +14,24 @@ typedef struct __attribute__((objc_boxable)) MGLCoordinateSpan {
CLLocationDegrees longitudeDelta;
} MGLCoordinateSpan;
+/* Defines a point on the map in Mercator projection for a specific zoom level. */
+typedef struct __attribute__((objc_boxable)) MGLMapPoint {
+ /** X coordinate representing a longitude in Mercator projection. */
+ CGFloat x;
+ /** Y coordinate representing a latitide in Mercator projection. */
+ CGFloat y;
+ /** Zoom level at which the X and Y coordinates are valid. */
+ CGFloat zoomLevel;
+} MGLMapPoint;
+
+/* Defines a 4x4 matrix. */
+typedef struct MGLMatrix4 {
+ double m00, m01, m02, m03;
+ double m10, m11, m12, m13;
+ double m20, m21, m22, m23;
+ double m30, m31, m32, m33;
+} MGLMatrix4;
+
/**
Creates a new `MGLCoordinateSpan` from the given latitudinal and longitudinal
deltas.
@@ -26,6 +44,17 @@ NS_INLINE MGLCoordinateSpan MGLCoordinateSpanMake(CLLocationDegrees latitudeDelt
}
/**
+ Creates a new `MGLMapPoint` from the given X and Y coordinates, and zoom level.
+ */
+NS_INLINE MGLMapPoint MGLMapPointMake(CGFloat x, CGFloat y, CGFloat zoomLevel) {
+ MGLMapPoint point;
+ point.x = x;
+ point.y = y;
+ point.zoomLevel = zoomLevel;
+ return point;
+}
+
+/**
Returns `YES` if the two coordinate spans represent the same latitudinal change
and the same longitudinal change.
*/
@@ -181,4 +210,7 @@ NS_INLINE CLLocationDegrees MGLDegreesFromRadians(CGFloat radians) {
return radians * 180 / M_PI;
}
+/** Returns Mercator projection of a WGS84 coordinate at the specified zoom level. */
+extern MGL_EXPORT MGLMapPoint MGLMapPointForCoordinate(CLLocationCoordinate2D coordinate, double zoomLevel);
+
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLGeometry.mm b/platform/darwin/src/MGLGeometry.mm
index 715a70f0b8..6785779570 100644
--- a/platform/darwin/src/MGLGeometry.mm
+++ b/platform/darwin/src/MGLGeometry.mm
@@ -106,3 +106,19 @@ CGPoint MGLPointRounded(CGPoint point) {
#endif
return CGPointMake(round(point.x * scaleFactor) / scaleFactor, round(point.y * scaleFactor) / scaleFactor);
}
+
+MGLMapPoint MGLMapPointForCoordinate(CLLocationCoordinate2D coordinate, double zoomLevel) {
+ mbgl::Point<double> projectedCoordinate = mbgl::Projection::project(MGLLatLngFromLocationCoordinate2D(coordinate), std::pow(2.0, zoomLevel));
+ return MGLMapPointMake(projectedCoordinate.x, projectedCoordinate.y, zoomLevel);
+}
+
+MGLMatrix4 MGLMatrix4Make(std::array<double, 16> array) {
+ MGLMatrix4 mat4 = {
+ .m00 = array[0], .m01 = array[1], .m02 = array[2], .m03 = array[3],
+ .m10 = array[4], .m11 = array[5], .m12 = array[6], .m13 = array[7],
+ .m20 = array[8], .m21 = array[9], .m22 = array[10], .m23 = array[11],
+ .m30 = array[12], .m31 = array[13], .m32 = array[14], .m33 = array[15]
+ };
+ return mat4;
+}
+
diff --git a/platform/darwin/src/MGLGeometry_Private.h b/platform/darwin/src/MGLGeometry_Private.h
index 8b9c6c2327..0bff9b09f5 100644
--- a/platform/darwin/src/MGLGeometry_Private.h
+++ b/platform/darwin/src/MGLGeometry_Private.h
@@ -128,3 +128,5 @@ MGLRadianCoordinate2D MGLRadianCoordinateAtDistanceFacingDirection(MGLRadianCoor
CLLocationDirection MGLDirectionBetweenCoordinates(CLLocationCoordinate2D firstCoordinate, CLLocationCoordinate2D secondCoordinate);
CGPoint MGLPointRounded(CGPoint point);
+
+MGLMatrix4 MGLMatrix4Make(std::array<double, 16> mat);
diff --git a/platform/darwin/src/MGLHeatmapStyleLayer.h b/platform/darwin/src/MGLHeatmapStyleLayer.h
index 35095fd52e..ad7ba5de01 100644
--- a/platform/darwin/src/MGLHeatmapStyleLayer.h
+++ b/platform/darwin/src/MGLHeatmapStyleLayer.h
@@ -13,10 +13,11 @@ NS_ASSUME_NONNULL_BEGIN
A heatmap visualizes the spatial distribution of a large, dense set of point
data, using color to avoid cluttering the map with individual points at low
zoom levels. The points are weighted by an attribute you specify. Use a heatmap
- style layer in conjunction with point or point collection features in vector
- tiles loaded by an `MGLVectorSource` object or `MGLPointAnnotation`,
- `MGLPointFeature`, `MGLPointCollection`, or `MGLPointCollectionFeature`
- instances in an `MGLShapeSource` object.
+ style layer in conjunction with point or point collection features. These
+ features can come from vector tiles loaded by an `MGLVectorTileSource` object,
+ or they can be `MGLPointAnnotation`, `MGLPointFeature`, `MGLPointCollection`,
+ or `MGLPointCollectionFeature` instances in an `MGLShapeSource` or
+ `MGLComputedShapeSource` object.
Consider accompanying a heatmap style layer with an `MGLCircleStyleLayer` or
`MGLSymbolStyleLayer` at high zoom levels. If you are unsure whether the point
@@ -35,10 +36,10 @@ NS_ASSUME_NONNULL_BEGIN
```swift
let layer = MGLHeatmapStyleLayer(identifier: "earthquake-heat", source: earthquakes)
- layer.heatmapWeight = NSExpression(format: "FUNCTION(magnitude, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
+ layer.heatmapWeight = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:(magnitude, 'linear', nil, %@)",
[0: 0,
6: 1])
- layer.heatmapIntensity = NSExpression(format: "FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
+ layer.heatmapIntensity = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)",
[0: 1,
9: 3])
mapView.style?.addLayer(layer)
@@ -64,9 +65,11 @@ MGL_EXPORT
#pragma mark - Accessing the Paint Attributes
+#if TARGET_OS_IPHONE
/**
- Defines the color of each point based on its density value in a heatmap. Should
- be an expression that uses `$heatmapDensity` as input.
+ The color of each screen point based on its density value in a heatmap. This
+ property is normally set to an interpolation or step expression with the
+ `$heatmapDensity` value as its input.
The default value of this property is an expression that evaluates to a rainbow
color scale from blue to red. Set this property to `nil` to reset it to the
@@ -84,17 +87,40 @@ MGL_EXPORT
feature attributes.
*/
@property (nonatomic, null_resettable) NSExpression *heatmapColor;
+#else
+/**
+ The color of each screen point based on its density value in a heatmap. This
+ property is normally set to an interpolation or step expression with the
+ `$heatmapDensity` value as its input.
+
+ The default value of this property is an expression that evaluates to a rainbow
+ color scale from blue to red. Set this property to `nil` to reset it to the
+ default value.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$heatmapDensity` variable
+
+ This property does not support applying interpolation or step functions to
+ feature attributes.
+ */
+@property (nonatomic, null_resettable) NSExpression *heatmapColor;
+#endif
/**
Similar to `heatmapWeight` but controls the intensity of the heatmap globally.
Primarily used for adjusting the heatmap based on zoom level.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -116,11 +142,11 @@ MGL_EXPORT
The global opacity at which the heatmap layer will be drawn.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -145,11 +171,11 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `30`. Set this property to `nil` to reset it to the default value.
+ 30. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 1
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -171,11 +197,11 @@ MGL_EXPORT
Especially useful when combined with clustering.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
diff --git a/platform/darwin/src/MGLHillshadeStyleLayer.h b/platform/darwin/src/MGLHillshadeStyleLayer.h
index b2eeb59aba..224680160a 100644
--- a/platform/darwin/src/MGLHillshadeStyleLayer.h
+++ b/platform/darwin/src/MGLHillshadeStyleLayer.h
@@ -36,7 +36,7 @@ typedef NS_ENUM(NSUInteger, MGLHillshadeIlluminationAnchor) {
To display posterized hillshading based on vector shapes, as with the <a
href="https://www.mapbox.com/vector-tiles/mapbox-terrain/">Mapbox Terrain</a>
- source, use an `MGLVectorSource` object in conjunction with several
+ source, use an `MGLVectorTileSource` object in conjunction with several
`MGLFillStyleLayer` objects.
You can access an existing hillshade style layer using the
@@ -75,6 +75,7 @@ MGL_EXPORT
#pragma mark - Accessing the Paint Attributes
+#if TARGET_OS_IPHONE
/**
The shading color used to accentuate rugged terrain like sharp cliffs and
gorges.
@@ -95,6 +96,28 @@ MGL_EXPORT
feature attributes.
*/
@property (nonatomic, null_resettable) NSExpression *hillshadeAccentColor;
+#else
+/**
+ The shading color used to accentuate rugged terrain like sharp cliffs and
+ gorges.
+
+ The default value of this property is an expression that evaluates to
+ `NSColor.blackColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable
+
+ This property does not support applying interpolation or step functions to
+ feature attributes.
+ */
+@property (nonatomic, null_resettable) NSExpression *hillshadeAccentColor;
+#endif
/**
The transition affecting any changes to this layer’s `hillshadeAccentColor` property.
@@ -107,11 +130,11 @@ MGL_EXPORT
Intensity of the hillshade
The default value of this property is an expression that evaluates to the float
- `0.5`. Set this property to `nil` to reset it to the default value.
+ 0.5. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -129,6 +152,7 @@ MGL_EXPORT
*/
@property (nonatomic) MGLTransition hillshadeExaggerationTransition;
+#if TARGET_OS_IPHONE
/**
The shading color of areas that faces towards the light source.
@@ -148,6 +172,27 @@ MGL_EXPORT
feature attributes.
*/
@property (nonatomic, null_resettable) NSExpression *hillshadeHighlightColor;
+#else
+/**
+ The shading color of areas that faces towards the light source.
+
+ The default value of this property is an expression that evaluates to
+ `NSColor.whiteColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable
+
+ This property does not support applying interpolation or step functions to
+ feature attributes.
+ */
+@property (nonatomic, null_resettable) NSExpression *hillshadeHighlightColor;
+#endif
/**
The transition affecting any changes to this layer’s `hillshadeHighlightColor` property.
@@ -187,11 +232,11 @@ MGL_EXPORT
`hillshadeIlluminationAnchor` is set to `MGLHillshadeIlluminationAnchorMap`.
The default value of this property is an expression that evaluates to the float
- `335`. Set this property to `nil` to reset it to the default value.
+ 335. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 359 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -202,6 +247,7 @@ MGL_EXPORT
*/
@property (nonatomic, null_resettable) NSExpression *hillshadeIlluminationDirection;
+#if TARGET_OS_IPHONE
/**
The shading color of areas that face away from the light source.
@@ -221,6 +267,27 @@ MGL_EXPORT
feature attributes.
*/
@property (nonatomic, null_resettable) NSExpression *hillshadeShadowColor;
+#else
+/**
+ The shading color of areas that face away from the light source.
+
+ The default value of this property is an expression that evaluates to
+ `NSColor.blackColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable
+
+ This property does not support applying interpolation or step functions to
+ feature attributes.
+ */
+@property (nonatomic, null_resettable) NSExpression *hillshadeShadowColor;
+#endif
/**
The transition affecting any changes to this layer’s `hillshadeShadowColor` property.
diff --git a/platform/darwin/src/MGLLight.h b/platform/darwin/src/MGLLight.h
index d7e64cbfad..cf4aa50112 100644
--- a/platform/darwin/src/MGLLight.h
+++ b/platform/darwin/src/MGLLight.h
@@ -128,6 +128,7 @@ MGL_EXPORT
*/
@property (nonatomic) MGLTransition positionTransition;
+#if TARGET_OS_IPHONE
/**
Color tint for lighting extruded geometries.
@@ -150,6 +151,30 @@ MGL_EXPORT
light property in the Mapbox Style Specification.
*/
@property (nonatomic) NSExpression *color;
+#else
+/**
+ Color tint for lighting extruded geometries.
+
+ The default value of this property is an expression that evaluates to
+ `NSColor.whiteColor`.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable
+
+ This property does not support applying interpolation or step functions to
+ feature attributes.
+
+ This property corresponds to the <a
+ href="https://www.mapbox.com/mapbox-gl-js/style-spec/#light-color"><code>color</code></a>
+ light property in the Mapbox Style Specification.
+ */
+@property (nonatomic) NSExpression *color;
+#endif
/**
The transition affecting any changes to this layer’s `color` property.
@@ -163,11 +188,11 @@ MGL_EXPORT
more extreme contrast.
The default value of this property is an expression that evaluates to the float
- `0.5`.
+ 0.5.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h
index 003f48ae43..a7510142fc 100644
--- a/platform/darwin/src/MGLLineStyleLayer.h
+++ b/platform/darwin/src/MGLLineStyleLayer.h
@@ -78,9 +78,10 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
polylines on the map.
Use a line style layer to configure the visual appearance of polyline or
- multipolyline features in vector tiles loaded by an `MGLVectorSource` object or
- `MGLPolyline`, `MGLPolylineFeature`, `MGLMultiPolyline`, or
- `MGLMultiPolylineFeature` instances in an `MGLShapeSource` object.
+ multipolyline features. These features can come from vector tiles loaded by an
+ `MGLVectorTileSource` object, or they can be `MGLPolyline`,
+ `MGLPolylineFeature`, `MGLMultiPolyline`, or `MGLMultiPolylineFeature`
+ instances in an `MGLShapeSource` or `MGLComputedShapeSource` object.
You can access an existing line style layer using the
`-[MGLStyle layerWithIdentifier:]` method if you know its identifier;
@@ -93,7 +94,7 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslationAnchor) {
```swift
let layer = MGLLineStyleLayer(identifier: "trails-path", source: trails)
layer.sourceLayerIdentifier = "trails"
- layer.lineWidth = NSExpression(format: "FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'exponential', 1.5, %@)",
+ layer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'exponential', 1.5, %@)",
[14: 2,
18: 20])
layer.lineColor = NSExpression(forConstantValue: UIColor.brown)
@@ -179,7 +180,7 @@ MGL_EXPORT
Used to automatically convert miter joins to bevel joins for sharp angles.
The default value of this property is an expression that evaluates to the float
- `2`. Set this property to `nil` to reset it to the default value.
+ 2. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `lineJoin` is set to an
expression that evaluates to `miter`. Otherwise, it is ignored.
@@ -201,7 +202,7 @@ MGL_EXPORT
Used to automatically convert round joins to miter joins for shallow angles.
The default value of this property is an expression that evaluates to the float
- `1.05`. Set this property to `nil` to reset it to the default value.
+ 1.05. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `lineJoin` is set to an
expression that evaluates to `round`. Otherwise, it is ignored.
@@ -227,11 +228,11 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -247,6 +248,7 @@ MGL_EXPORT
*/
@property (nonatomic) MGLTransition lineBlurTransition;
+#if TARGET_OS_IPHONE
/**
The color with which the line will be drawn.
@@ -267,6 +269,28 @@ MGL_EXPORT
feature attributes
*/
@property (nonatomic, null_resettable) NSExpression *lineColor;
+#else
+/**
+ The color with which the line will be drawn.
+
+ The default value of this property is an expression that evaluates to
+ `NSColor.blackColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ This property is only applied to the style if `linePattern` is set to `nil`.
+ Otherwise, it is ignored.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable and/or
+ feature attributes
+ */
+@property (nonatomic, null_resettable) NSExpression *lineColor;
+#endif
/**
The transition affecting any changes to this layer’s `lineColor` property.
@@ -291,7 +315,7 @@ MGL_EXPORT
You can set this property to an expression containing any of the following:
- * Constant array values
+ * Constant array values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -319,11 +343,11 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -348,7 +372,7 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
@@ -372,11 +396,11 @@ MGL_EXPORT
The opacity at which the line will be drawn.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -518,11 +542,11 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
diff --git a/platform/darwin/src/MGLLineStyleLayer.mm b/platform/darwin/src/MGLLineStyleLayer.mm
index 4e6ff27b39..619cc70afe 100644
--- a/platform/darwin/src/MGLLineStyleLayer.mm
+++ b/platform/darwin/src/MGLLineStyleLayer.mm
@@ -390,7 +390,8 @@ namespace mbgl {
if (propertyValue.isUndefined()) {
propertyValue = self.rawLayer->getDefaultLinePattern();
}
- return MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ NSExpression *expression = MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ return expression.mgl_expressionByReplacingTokensWithKeyPaths;
}
- (void)setLinePatternTransition:(MGLTransition )transition {
diff --git a/platform/darwin/src/MGLMapSnapshotter.h b/platform/darwin/src/MGLMapSnapshotter.h
index 426ab1bb00..976213c8ba 100644
--- a/platform/darwin/src/MGLMapSnapshotter.h
+++ b/platform/darwin/src/MGLMapSnapshotter.h
@@ -140,7 +140,7 @@ typedef void (^MGLMapSnapshotCompletionHandler)(MGLMapSnapshot* _Nullable snapsh
```swift
let camera = MGLMapCamera(lookingAtCenter: CLLocationCoordinate2D(latitude: 37.7184, longitude: -122.4365), fromDistance: 100, pitch: 20, heading: 0)
- let options = MGLMapSnapshotOptions(styleURL: MGLStyle.satelliteStreetsStyleURL(), camera: camera, size: CGSize(width: 320, height: 480))
+ let options = MGLMapSnapshotOptions(styleURL: MGLStyle.satelliteStreetsStyleURL, camera: camera, size: CGSize(width: 320, height: 480))
options.zoomLevel = 10
let snapshotter = MGLMapSnapshotter(options: options)
diff --git a/platform/darwin/src/MGLNetworkConfiguration.h b/platform/darwin/src/MGLNetworkConfiguration.h
index 644291ee13..2db46d78c5 100644
--- a/platform/darwin/src/MGLNetworkConfiguration.h
+++ b/platform/darwin/src/MGLNetworkConfiguration.h
@@ -13,7 +13,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface MGLNetworkConfiguration : NSObject
/// Returns the shared instance of the `MGLNetworkConfiguration` class.
-+ (instancetype)sharedManager;
+@property (class, nonatomic, readonly) MGLNetworkConfiguration *sharedManager;
/// The current API base URL. If `nil`, the Mapbox default base API URL is in use.
@property (atomic, nullable) NSURL *apiBaseURL;
diff --git a/platform/darwin/src/MGLOfflineStorage.h b/platform/darwin/src/MGLOfflineStorage.h
index b009f893b3..a1f3e686c2 100644
--- a/platform/darwin/src/MGLOfflineStorage.h
+++ b/platform/darwin/src/MGLOfflineStorage.h
@@ -70,7 +70,7 @@ typedef NSString *MGLOfflinePackUserInfoKey NS_EXTENSIBLE_STRING_ENUM;
*/
extern MGL_EXPORT const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyState;
-extern MGL_EXPORT NSString * const MGLOfflinePackStateUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyState")));
+extern MGL_EXPORT NSString * const MGLOfflinePackStateUserInfoKey __attribute__((unavailable("Use MGLOfflinePackUserInfoKeyState")));
/**
The key for an `NSValue` object that indicates an offline pack’s current
@@ -81,7 +81,7 @@ extern MGL_EXPORT NSString * const MGLOfflinePackStateUserInfoKey __attribute__(
*/
extern MGL_EXPORT const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyProgress;
-extern MGL_EXPORT NSString * const MGLOfflinePackProgressUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyProgress")));
+extern MGL_EXPORT NSString * const MGLOfflinePackProgressUserInfoKey __attribute__((unavailable("Use MGLOfflinePackUserInfoKeyProgress")));
/**
The key for an `NSError` object that is encountered in the course of
@@ -91,7 +91,7 @@ extern MGL_EXPORT NSString * const MGLOfflinePackProgressUserInfoKey __attribute
*/
extern MGL_EXPORT const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyError;
-extern MGL_EXPORT NSString * const MGLOfflinePackErrorUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyError")));
+extern MGL_EXPORT NSString * const MGLOfflinePackErrorUserInfoKey __attribute__((unavailable("Use MGLOfflinePackUserInfoKeyError")));
/**
The key for an `NSNumber` object that indicates the maximum number of
@@ -103,7 +103,7 @@ extern MGL_EXPORT NSString * const MGLOfflinePackErrorUserInfoKey __attribute__(
*/
extern MGL_EXPORT const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyMaximumCount;
-extern MGL_EXPORT NSString * const MGLOfflinePackMaximumCountUserInfoKey __attribute__((deprecated("Use MGLOfflinePackUserInfoKeyMaximumCount")));
+extern MGL_EXPORT NSString * const MGLOfflinePackMaximumCountUserInfoKey __attribute__((unavailable("Use MGLOfflinePackUserInfoKeyMaximumCount")));
/**
A block to be called once an offline pack has been completely created and
@@ -170,7 +170,7 @@ MGL_EXPORT
/**
Returns the shared offline storage object.
*/
-+ (instancetype)sharedOfflineStorage;
+@property (class, nonatomic, readonly) MGLOfflineStorage *sharedOfflineStorage;
#pragma mark - Accessing the Delegate
diff --git a/platform/darwin/src/MGLOfflineStorage.mm b/platform/darwin/src/MGLOfflineStorage.mm
index 7085aa58e5..4d999144e8 100644
--- a/platform/darwin/src/MGLOfflineStorage.mm
+++ b/platform/darwin/src/MGLOfflineStorage.mm
@@ -26,13 +26,9 @@ const NSNotificationName MGLOfflinePackErrorNotification = @"MGLOfflinePackError
const NSNotificationName MGLOfflinePackMaximumMapboxTilesReachedNotification = @"MGLOfflinePackMaximumMapboxTilesReached";
const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyState = @"State";
-NSString * const MGLOfflinePackStateUserInfoKey = MGLOfflinePackUserInfoKeyState;
const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyProgress = @"Progress";
-NSString * const MGLOfflinePackProgressUserInfoKey = MGLOfflinePackUserInfoKeyProgress;
const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyError = @"Error";
-NSString * const MGLOfflinePackErrorUserInfoKey = MGLOfflinePackUserInfoKeyError;
const MGLOfflinePackUserInfoKey MGLOfflinePackUserInfoKeyMaximumCount = @"MaximumCount";
-NSString * const MGLOfflinePackMaximumCountUserInfoKey = MGLOfflinePackUserInfoKeyMaximumCount;
@interface MGLOfflineStorage ()
diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.h b/platform/darwin/src/MGLOpenGLStyleLayer.h
index 0b494e8062..df8d2c5365 100644
--- a/platform/darwin/src/MGLOpenGLStyleLayer.h
+++ b/platform/darwin/src/MGLOpenGLStyleLayer.h
@@ -1,9 +1,11 @@
#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>
+#import <QuartzCore/QuartzCore.h>
#import "MGLFoundation.h"
#import "MGLStyleValue.h"
#import "MGLStyleLayer.h"
+#import "MGLGeometry.h"
NS_ASSUME_NONNULL_BEGIN
@@ -17,6 +19,7 @@ typedef struct MGLStyleLayerDrawingContext {
CLLocationDirection direction;
CGFloat pitch;
CGFloat fieldOfView;
+ MGLMatrix4 projectionMatrix;
} MGLStyleLayerDrawingContext;
MGL_EXPORT
diff --git a/platform/darwin/src/MGLOpenGLStyleLayer.mm b/platform/darwin/src/MGLOpenGLStyleLayer.mm
index 8933a77382..d89fbc80c3 100644
--- a/platform/darwin/src/MGLOpenGLStyleLayer.mm
+++ b/platform/darwin/src/MGLOpenGLStyleLayer.mm
@@ -3,53 +3,53 @@
#import "MGLMapView_Private.h"
#import "MGLStyle_Private.h"
#import "MGLStyleLayer_Private.h"
+#import "MGLGeometry_Private.h"
#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/math/wrap.hpp>
-/**
- Runs the preparation handler block contained in the given context, which is
- implicitly an instance of `MGLOpenGLStyleLayer`.
+class MGLOpenGLLayerHost : public mbgl::style::CustomLayerHost {
+public:
+ MGLOpenGLLayerHost(MGLOpenGLStyleLayer *styleLayer) {
+ layerRef = styleLayer;
+ layer = nil;
+ }
- @param context An `MGLOpenGLStyleLayer` instance that was provided as context
- when creating an OpenGL style layer.
- */
-void MGLPrepareCustomStyleLayer(void *context) {
- MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer *)context;
- [layer didMoveToMapView:layer.style.mapView];
-}
+ void initialize() {
+ if (layerRef == nil) return;
+ else if (layer == nil) layer = layerRef;
-/**
- Runs the drawing handler block contained in the given context, which is
- implicitly an instance of `MGLOpenGLStyleLayer`.
+ [layer didMoveToMapView:layer.style.mapView];
+ }
- @param context An `MGLOpenGLStyleLayer` instance that was provided as context
- when creating an OpenGL style layer.
- */
-void MGLDrawCustomStyleLayer(void *context, const mbgl::style::CustomLayerRenderParameters &params) {
- MGLOpenGLStyleLayer *layer = (__bridge MGLOpenGLStyleLayer *)context;
- MGLStyleLayerDrawingContext drawingContext = {
- .size = CGSizeMake(params.width, params.height),
- .centerCoordinate = CLLocationCoordinate2DMake(params.latitude, params.longitude),
- .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.style.mapView withContext:drawingContext];
-}
+ void render(const mbgl::style::CustomLayerRenderParameters &params) {
+ if(!layer) return;
+
+ MGLStyleLayerDrawingContext drawingContext = {
+ .size = CGSizeMake(params.width, params.height),
+ .centerCoordinate = CLLocationCoordinate2DMake(params.latitude, params.longitude),
+ .zoomLevel = params.zoom,
+ .direction = mbgl::util::wrap(params.bearing, 0., 360.),
+ .pitch = static_cast<CGFloat>(params.pitch),
+ .fieldOfView = static_cast<CGFloat>(params.fieldOfView),
+ .projectionMatrix = MGLMatrix4Make(params.projectionMatrix)
+ };
+ [layer drawInMapView:layer.style.mapView withContext:drawingContext];
+ }
-/**
- Runs the completion handler block contained in the given context, which is
- implicitly an instance of `MGLOpenGLStyleLayer`.
+ void contextLost() {}
- @param context An `MGLOpenGLStyleLayer` instance that was provided as context
- when creating an OpenGL style layer.
- */
-void MGLFinishCustomStyleLayer(void *context) {
- MGLOpenGLStyleLayer *layer = (__bridge_transfer MGLOpenGLStyleLayer *)context;
- [layer willMoveFromMapView:layer.style.mapView];
-}
+ void deinitialize() {
+ if (layer == nil) return;
+
+ [layer willMoveFromMapView:layer.style.mapView];
+ layerRef = layer;
+ layer = nil;
+ }
+private:
+ __weak MGLOpenGLStyleLayer * layerRef;
+ MGLOpenGLStyleLayer * layer = nil;
+};
/**
An `MGLOpenGLStyleLayer` is a style layer that is rendered by OpenGL code that
@@ -98,10 +98,7 @@ void MGLFinishCustomStyleLayer(void *context) {
*/
- (instancetype)initWithIdentifier:(NSString *)identifier {
auto layer = std::make_unique<mbgl::style::CustomLayer>(identifier.UTF8String,
- MGLPrepareCustomStyleLayer,
- MGLDrawCustomStyleLayer,
- MGLFinishCustomStyleLayer,
- (__bridge_retained void *)self);
+ std::make_unique<MGLOpenGLLayerHost>(self));
return self = [super initWithPendingLayer:std::move(layer)];
}
@@ -110,22 +107,15 @@ void MGLFinishCustomStyleLayer(void *context) {
}
#pragma mark - Adding to and removing from a map view
-
-- (void)setStyle:(MGLStyle *)style {
- if (_style && style) {
- [NSException raise:@"MGLLayerReuseException"
- format:@"%@ cannot be added to more than one MGLStyle at a time.", self];
- }
- _style = style;
-}
-
- (void)addToStyle:(MGLStyle *)style belowLayer:(MGLStyleLayer *)otherLayer {
self.style = style;
+ self.style.openGLLayers[self.identifier] = self;
[super addToStyle:style belowLayer:otherLayer];
}
- (void)removeFromStyle:(MGLStyle *)style {
[super removeFromStyle:style];
+ self.style.openGLLayers[self.identifier] = nil;
self.style = nil;
}
diff --git a/platform/darwin/src/MGLPointAnnotation.h b/platform/darwin/src/MGLPointAnnotation.h
index 1ef0962f99..3dac7a969c 100644
--- a/platform/darwin/src/MGLPointAnnotation.h
+++ b/platform/darwin/src/MGLPointAnnotation.h
@@ -15,7 +15,7 @@ NS_ASSUME_NONNULL_BEGIN
You can add point shapes to the map by adding them to an `MGLShapeSource`
object. Configure the appearance of an `MGLShapeSource`’s or
- `MGLVectorSource`’s point shapes collectively using an `MGLCircleStyleLayer` or
+ `MGLVectorTileSource`’s point shapes collectively using an `MGLCircleStyleLayer` or
`MGLSymbolStyleLayer` object.
For more interactivity, add a selectable point annotation to a map view using
@@ -28,7 +28,8 @@ NS_ASSUME_NONNULL_BEGIN
default content of the annotation’s callout (on iOS) or popover (on macOS).
To group multiple related points together in one shape, use an
- `MGLPointCollection` or `MGLShapeCollection` object.
+ `MGLPointCollection` or `MGLShapeCollection` object. To access
+ a point’s attributes, use an `MGLPointFeature` object.
A point shape is known as a
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.2">Point</a> geometry
diff --git a/platform/darwin/src/MGLPointCollection.h b/platform/darwin/src/MGLPointCollection.h
index 74b30385a0..65ce95cb0f 100644
--- a/platform/darwin/src/MGLPointCollection.h
+++ b/platform/darwin/src/MGLPointCollection.h
@@ -14,8 +14,9 @@
You can add point collections to the map by adding them to an `MGLShapeSource`
object. Configure the appearance of an `MGLShapeSource`’s or
- `MGLVectorSource`’s point collections collectively using an
- `MGLCircleStyleLayer` or `MGLSymbolStyleLayer` object.
+ `MGLVectorTileSource`’s point collections collectively using an
+ `MGLCircleStyleLayer` or `MGLSymbolStyleLayer` object. To access a point
+ collection’s attributes, use an `MGLPointCollectionFeature` object.
You cannot add an `MGLPointCollection` object directly to a map view as an
annotation. However, you can create individual `MGLPointAnnotation` objects
diff --git a/platform/darwin/src/MGLPolygon.h b/platform/darwin/src/MGLPolygon.h
index 3fcc1be76d..190b6df9c5 100644
--- a/platform/darwin/src/MGLPolygon.h
+++ b/platform/darwin/src/MGLPolygon.h
@@ -17,8 +17,9 @@ NS_ASSUME_NONNULL_BEGIN
You can add polygon shapes to the map by adding them to an `MGLShapeSource`
object. Configure the appearance of an `MGLShapeSource`’s or
- `MGLVectorSource`’s polygons collectively using an `MGLFillStyleLayer` or
- `MGLSymbolStyleLayer` object.
+ `MGLVectorTileSource`’s polygons collectively using an `MGLFillStyleLayer` or
+ `MGLSymbolStyleLayer` object. To access a polygon’s attributes, use an
+ `MGLPolygonFeature` object.
Alternatively, you can add a polygon overlay directly to a map view using the
`-[MGLMapView addAnnotation:]` or `-[MGLMapView addOverlay:]` method. Configure
@@ -95,8 +96,8 @@ MGL_EXPORT
You can add multipolygon shapes to the map by adding them to an
`MGLShapeSource` object. Configure the appearance of an `MGLShapeSource`’s or
- `MGLVectorSource`’s multipolygons collectively using an `MGLFillStyleLayer` or
- `MGLSymbolStyleLayer` object.
+ `MGLVectorTileSource`’s multipolygons collectively using an `MGLFillStyleLayer`
+ or `MGLSymbolStyleLayer` object.
You cannot add an `MGLMultiPolygon` object directly to a map view using
`-[MGLMapView addAnnotation:]` or `-[MGLMapView addOverlay:]`. However, you can
diff --git a/platform/darwin/src/MGLPolyline.h b/platform/darwin/src/MGLPolyline.h
index e46baa91cc..b1fca5bf28 100644
--- a/platform/darwin/src/MGLPolyline.h
+++ b/platform/darwin/src/MGLPolyline.h
@@ -17,8 +17,9 @@ NS_ASSUME_NONNULL_BEGIN
You can add polyline shapes to the map by adding them to an `MGLShapeSource`
object. Configure the appearance of an `MGLShapeSource`’s or
- `MGLVectorSource`’s polylines collectively using an `MGLLineStyleLayer` or
- `MGLSymbolStyleLayer` object.
+ `MGLVectorTileSource`’s polylines collectively using an `MGLLineStyleLayer` or
+ `MGLSymbolStyleLayer` object. To access a polyline’s attributes, use an
+ `MGLPolylineFeature` object.
Alternatively, you can add a polyline overlay directly to a map view using the
`-[MGLMapView addAnnotation:]` or `-[MGLMapView addOverlay:]` method. Configure
@@ -74,8 +75,8 @@ MGL_EXPORT
You can add multipolyline shapes to the map by adding them to an
`MGLShapeSource` object. Configure the appearance of an `MGLShapeSource`’s or
- `MGLVectorSource`’s multipolylines collectively using an `MGLLineStyleLayer` or
- `MGLSymbolStyleLayer` object.
+ `MGLVectorTileSource`’s multipolylines collectively using an
+ `MGLLineStyleLayer` or `MGLSymbolStyleLayer` object.
You cannot add an `MGLMultiPolyline` object directly to a map view using
`-[MGLMapView addAnnotation:]` or `-[MGLMapView addOverlay:]`. However, you can
diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm
index e011d09215..26e3518cd8 100644
--- a/platform/darwin/src/MGLPolyline.mm
+++ b/platform/darwin/src/MGLPolyline.mm
@@ -72,9 +72,12 @@
if (count > 1 || middle > traveled) {
for (NSUInteger i = 0; i < count; i++) {
-
+
+ // Avoid a heap buffer overflow when there are only two coordinates.
+ NSUInteger nextIndex = (i + 1 == count) ? 0 : 1;
+
MGLRadianCoordinate2D from = MGLRadianCoordinateFromLocationCoordinate(coordinates[i]);
- MGLRadianCoordinate2D to = MGLRadianCoordinateFromLocationCoordinate(coordinates[i + 1]);
+ MGLRadianCoordinate2D to = MGLRadianCoordinateFromLocationCoordinate(coordinates[i + nextIndex]);
if (traveled >= middle) {
double overshoot = middle - traveled;
@@ -91,7 +94,6 @@
}
traveled += (MGLDistanceBetweenRadianCoordinates(from, to) * mbgl::util::EARTH_RADIUS_M);
-
}
}
diff --git a/platform/darwin/src/MGLRasterDEMSource.h b/platform/darwin/src/MGLRasterDEMSource.h
index d00912ca79..d439fe1645 100644
--- a/platform/darwin/src/MGLRasterDEMSource.h
+++ b/platform/darwin/src/MGLRasterDEMSource.h
@@ -1,6 +1,19 @@
#import "MGLFoundation.h"
-#import "MGLRasterSource.h"
+#import "MGLRasterTileSource.h"
+
+/**
+ An `NSNumber` object containing an unsigned integer that specifies the encoding
+ formula for raster-dem tilesets. The integer corresponds to one of
+ the constants described in `MGLDEMEncoding`.
+
+ The default value for this option is `MGLDEMEncodingMapbox`.
+
+ This option cannot be represented in a TileJSON or style JSON file. It is used
+ with the `MGLRasterDEMSource` class and is ignored when creating an
+ `MGLRasterTileSource` or `MGLVectorTileSource` object.
+ */
+extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionDEMEncoding;
/**
`MGLRasterDEMSource` is a map content source that supplies rasterized
@@ -32,6 +45,6 @@
```
*/
MGL_EXPORT
-@interface MGLRasterDEMSource : MGLRasterSource
+@interface MGLRasterDEMSource : MGLRasterTileSource
@end
diff --git a/platform/darwin/src/MGLRasterDEMSource.mm b/platform/darwin/src/MGLRasterDEMSource.mm
index d8639b70e3..27614b9ef4 100644
--- a/platform/darwin/src/MGLRasterDEMSource.mm
+++ b/platform/darwin/src/MGLRasterDEMSource.mm
@@ -1,6 +1,6 @@
#import "MGLRasterDEMSource.h"
-#import "MGLRasterSource_Private.h"
+#import "MGLRasterTileSource_Private.h"
#import "NSURL+MGLAdditions.h"
#import <mbgl/style/sources/raster_dem_source.hpp>
diff --git a/platform/darwin/src/MGLRasterStyleLayer.h b/platform/darwin/src/MGLRasterStyleLayer.h
index 7773246cad..bca9649e5d 100644
--- a/platform/darwin/src/MGLRasterStyleLayer.h
+++ b/platform/darwin/src/MGLRasterStyleLayer.h
@@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN
imagery on the map, especially raster tiles.
Use a raster style layer to configure the color parameters of raster tiles
- loaded by an `MGLRasterSource` object or raster images loaded by an
+ loaded by an `MGLRasterTileSource` object or raster images loaded by an
`MGLImageSource` object. For example, you could use a raster style layer to
render <a href="https://www.mapbox.com/satellite/">Mapbox Satellite</a>
imagery, a <a
@@ -64,7 +64,7 @@ MGL_EXPORT
brightness.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-raster-brightness-max"><code>raster-brightness-max</code></a>
@@ -72,7 +72,7 @@ MGL_EXPORT
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -97,7 +97,7 @@ MGL_EXPORT
brightness.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-raster-brightness-min"><code>raster-brightness-min</code></a>
@@ -105,7 +105,7 @@ MGL_EXPORT
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -129,11 +129,11 @@ MGL_EXPORT
Increase or reduce the contrast of the image.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between −1 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -157,11 +157,11 @@ MGL_EXPORT
This property is measured in milliseconds.
The default value of this property is an expression that evaluates to the float
- `300`. Set this property to `nil` to reset it to the default value.
+ 300. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -178,7 +178,7 @@ MGL_EXPORT
This property is measured in degrees.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#paint-raster-hue-rotate"><code>raster-hue-rotate</code></a>
@@ -210,11 +210,11 @@ MGL_EXPORT
The opacity at which the image will be drawn.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -236,11 +236,11 @@ MGL_EXPORT
Increase or reduce the saturation of the image.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between −1 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
diff --git a/platform/darwin/src/MGLRasterSource.h b/platform/darwin/src/MGLRasterTileSource.h
index 4f4b7c96c3..59b256d5e5 100644
--- a/platform/darwin/src/MGLRasterSource.h
+++ b/platform/darwin/src/MGLRasterTileSource.h
@@ -8,56 +8,59 @@ NS_ASSUME_NONNULL_BEGIN
/**
An `NSNumber` object containing a floating-point number that specifies the
width and height (measured in points) at which the map displays each raster
- image tile when the map’s zoom level is an integer. The raster source scales
- its images up or down when the map’s zoom level falls between two integers.
+ image tile when the map’s zoom level is an integer. The raster tile source
+ scales its images up or down when the map’s zoom level falls between two
+ integers.
The default value for this option is 512. Version 4 of the
<a href="https://www.mapbox.com/api-documentation/#maps">Mapbox Maps API</a>
requires a value of 256, as do many third-party tile servers, so consult your
provider’s documentation for the correct value.
- This option is only applicable to `MGLRasterSource` objects; it is ignored when
- initializing `MGLVectorSource` objects.
+ This option is only applicable to `MGLRasterTileSource` objects; it is ignored
+ when initializing `MGLVectorTileSource` objects.
*/
extern MGL_EXPORT const MGLTileSourceOption MGLTileSourceOptionTileSize;
/**
- `MGLRasterSource` is a map content source that supplies raster image tiles to
- be shown on the map. The location of and metadata about the tiles are defined
- either by an option dictionary or by an external file that conforms to the
+ `MGLRasterTileSource` is a map content source that supplies raster image tiles
+ to be shown on the map. The location of and metadata about the tiles are
+ defined either by an option dictionary or by an external file that conforms to
+ the
<a href="https://github.com/mapbox/tilejson-spec/">TileJSON specification</a>.
- A raster source is added to an `MGLStyle` object along with one or more
+ A raster tile source is added to an `MGLStyle` object along with one or more
`MGLRasterStyleLayer` objects. Use a raster style layer to control the
- appearance of content supplied by the raster source.
+ appearance of content supplied by the raster tile source.
Each
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-raster"><code>raster</code></a>
source defined by the style JSON file is represented at runtime by an
- `MGLRasterSource` object that you can use to initialize new style layers. You
+ `MGLRasterTileSource` object that you can use to initialize new style layers. You
can also add and remove sources dynamically using methods such as
`-[MGLStyle addSource:]` and `-[MGLStyle sourceWithIdentifier:]`.
### Example
```swift
- let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [
+ let source = MGLRasterTileSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [
.minimumZoomLevel: 9,
.maximumZoomLevel: 16,
.tileSize: 512,
.attributionInfos: [
- MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com"))
+ MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "https://mapbox.com"))
]
])
mapView.style?.addSource(source)
```
*/
MGL_EXPORT
-@interface MGLRasterSource : MGLTileSource
+@interface MGLRasterTileSource : MGLTileSource
#pragma mark Initializing a Source
/**
- Returns a raster source initialized with an identifier and configuration URL.
+ Returns a raster tile source initialized with an identifier and configuration
+ URL.
After initializing and configuring the source, add it to a map view’s style
using the `-[MGLStyle addSource:]` method.
@@ -77,13 +80,13 @@ MGL_EXPORT
which it is added.
@param configurationURL A URL to a TileJSON configuration file describing the
source’s contents and other metadata.
- @return An initialized raster source.
+ @return An initialized raster tile source.
*/
- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL;
/**
- Returns a raster source initialized with an identifier, configuration URL, and
- tile size.
+ Returns a raster tile source initialized with an identifier, configuration URL,
+ and tile size.
After initializing and configuring the source, add it to a map view’s style
using the `-[MGLStyle addSource:]` method.
@@ -98,14 +101,14 @@ MGL_EXPORT
@param configurationURL A URL to a TileJSON configuration file describing the
source’s contents and other metadata.
@param tileSize The width and height (measured in points) of each tiled image
- in the raster source. See the `MGLTileSourceOptionTileSize` documentation
- for details.
- @return An initialized raster source.
+ in the raster tile source. See the `MGLTileSourceOptionTileSize`
+ documentation for details.
+ @return An initialized raster tile source.
*/
- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL tileSize:(CGFloat)tileSize NS_DESIGNATED_INITIALIZER;
/**
- Returns a raster source initialized an identifier, tile URL templates, and
+ Returns a raster tile source initialized an identifier, tile URL templates, and
options.
Tile URL templates are strings that specify the URLs of the raster tile images
diff --git a/platform/darwin/src/MGLRasterSource.mm b/platform/darwin/src/MGLRasterTileSource.mm
index c47cc199eb..02cfef4ae8 100644
--- a/platform/darwin/src/MGLRasterSource.mm
+++ b/platform/darwin/src/MGLRasterTileSource.mm
@@ -1,4 +1,4 @@
-#import "MGLRasterSource_Private.h"
+#import "MGLRasterTileSource_Private.h"
#import "MGLMapView_Private.h"
#import "MGLSource_Private.h"
@@ -10,16 +10,16 @@
const MGLTileSourceOption MGLTileSourceOptionTileSize = @"MGLTileSourceOptionTileSize";
-static const CGFloat MGLRasterSourceClassicTileSize = 256;
-static const CGFloat MGLRasterSourceRetinaTileSize = 512;
+static const CGFloat MGLRasterTileSourceClassicTileSize = 256;
+static const CGFloat MGLRasterTileSourceRetinaTileSize = 512;
-@interface MGLRasterSource ()
+@interface MGLRasterTileSource ()
@property (nonatomic, readonly) mbgl::style::RasterSource *rawSource;
@end
-@implementation MGLRasterSource
+@implementation MGLRasterTileSource
- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL {
// The style specification default is 512, but 256 is the expected value for
@@ -28,7 +28,7 @@ static const CGFloat MGLRasterSourceRetinaTileSize = 512;
BOOL isMapboxURL = ([configurationURL.scheme isEqualToString:@"mapbox"]
&& [configurationURL.host containsString:@"."]
&& (!configurationURL.path.length || [configurationURL.path isEqualToString:@"/"]));
- CGFloat tileSize = isMapboxURL ? MGLRasterSourceClassicTileSize : MGLRasterSourceRetinaTileSize;
+ CGFloat tileSize = isMapboxURL ? MGLRasterTileSourceClassicTileSize : MGLRasterTileSourceRetinaTileSize;
return [self initWithIdentifier:identifier configurationURL:configurationURL tileSize:tileSize];
}
@@ -47,7 +47,7 @@ static const CGFloat MGLRasterSourceRetinaTileSize = 512;
- (instancetype)initWithIdentifier:(NSString *)identifier tileURLTemplates:(NS_ARRAY_OF(NSString *) *)tileURLTemplates options:(nullable NS_DICTIONARY_OF(MGLTileSourceOption, id) *)options {
mbgl::Tileset tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, options);
- uint16_t tileSize = MGLRasterSourceRetinaTileSize;
+ uint16_t tileSize = MGLRasterTileSourceRetinaTileSize;
if (NSNumber *tileSizeNumber = options[MGLTileSourceOptionTileSize]) {
if (![tileSizeNumber isKindOfClass:[NSNumber class]]) {
[NSException raise:NSInvalidArgumentException
diff --git a/platform/darwin/src/MGLRasterSource_Private.h b/platform/darwin/src/MGLRasterTileSource_Private.h
index 6f40fbc5a9..128dcb447d 100644
--- a/platform/darwin/src/MGLRasterSource_Private.h
+++ b/platform/darwin/src/MGLRasterTileSource_Private.h
@@ -1,4 +1,4 @@
-#import "MGLRasterSource.h"
+#import "MGLRasterTileSource.h"
#include <memory>
@@ -10,7 +10,7 @@ namespace mbgl {
NS_ASSUME_NONNULL_BEGIN
-@interface MGLRasterSource (Private)
+@interface MGLRasterTileSource (Private)
@property (nonatomic, readonly) mbgl::style::RasterSource *rawSource;
diff --git a/platform/darwin/src/MGLRendererConfiguration.h b/platform/darwin/src/MGLRendererConfiguration.h
index 31aad0a742..34c8e9628b 100644
--- a/platform/darwin/src/MGLRendererConfiguration.h
+++ b/platform/darwin/src/MGLRendererConfiguration.h
@@ -11,7 +11,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface MGLRendererConfiguration : NSObject
/** Returns an instance of the current renderer configuration. */
-+ (instancetype)currentConfiguration;
+@property (class, nonatomic, readonly) MGLRendererConfiguration *currentConfiguration;
/** The file source to use. Defaults to `mbgl::DefaultFileSource` */
@property (nonatomic, readonly) mbgl::DefaultFileSource *fileSource;
diff --git a/platform/darwin/src/MGLShape.h b/platform/darwin/src/MGLShape.h
index e965710552..e0ef0999db 100644
--- a/platform/darwin/src/MGLShape.h
+++ b/platform/darwin/src/MGLShape.h
@@ -12,21 +12,23 @@ NS_ASSUME_NONNULL_BEGIN
Create instances of `MGLPointAnnotation`, `MGLPointCollection`, `MGLPolyline`,
`MGLMultiPolyline`, `MGLPolygon`, `MGLMultiPolygon`, or `MGLShapeCollection` in
- order to use `MGLShape`'s methods. Do not create instances of `MGLShape` directly,
- and do not create your own subclasses of this class. The shape classes correspond
- to the <a href="https://tools.ietf.org/html/rfc7946#section-3.1">Geometry</a> object
+ order to use `MGLShape`'s methods. Do not create instances of `MGLShape`
+ directly, and do not create your own subclasses of this class. The shape
+ classes correspond to the
+ <a href="https://tools.ietf.org/html/rfc7946#section-3.1">Geometry</a> object
types in the GeoJSON standard, but some have nonstandard names for backwards
compatibility.
Although you do not create instances of this class directly, you can use its
`+[MGLShape shapeWithData:encoding:error:]` factory method to create one of the
- concrete subclasses of `MGLShape` noted above from GeoJSON data.
+ concrete subclasses of `MGLShape` noted above from GeoJSON data. To access a
+ shape’s attributes, use the corresponding `MGLFeature` class instead.
You can add shapes to the map by adding them to an `MGLShapeSource` object.
- Configure the appearance of an `MGLShapeSource`’s or `MGLVectorSource`’s shapes
- collectively using a concrete instance of `MGLVectorStyleLayer`. Alternatively,
- you can add some kinds of shapes directly to a map view as annotations or
- overlays.
+ Configure the appearance of an `MGLShapeSource`’s or `MGLVectorTileSource`’s
+ shapes collectively using a concrete instance of `MGLVectorStyleLayer`.
+ Alternatively, you can add some kinds of shapes directly to a map view as
+ annotations or overlays.
*/
MGL_EXPORT
@interface MGLShape : NSObject <MGLAnnotation, NSSecureCoding>
diff --git a/platform/darwin/src/MGLShapeCollection.h b/platform/darwin/src/MGLShapeCollection.h
index bb107ee7f0..bec482ca61 100644
--- a/platform/darwin/src/MGLShapeCollection.h
+++ b/platform/darwin/src/MGLShapeCollection.h
@@ -14,7 +14,7 @@ NS_ASSUME_NONNULL_BEGIN
`MGLShapeCollection` is most commonly used to add multiple shapes to a single
`MGLShapeSource`. Configure the appearance of an `MGLShapeSource`’s or
- `MGLVectorSource`’s shape collection collectively using an
+ `MGLVectorTileSource`’s shape collection collectively using an
`MGLSymbolStyleLayer` object, or use multiple instances of
`MGLCircleStyleLayer`, `MGLFillStyleLayer`, and `MGLLineStyleLayer` to
configure the appearance of each kind of shape inside the collection.
@@ -27,7 +27,8 @@ NS_ASSUME_NONNULL_BEGIN
To represent a collection of point, polyline, or polygon shapes, it may be more
convenient to use an `MGLPointCollection`, `MGLMultiPolyline`, or
- `MGLMultiPolygon` object, respectively.
+ `MGLMultiPolygon` object, respectively. To access a shape collection’s
+ attributes, use the corresponding `MGLFeature` object.
A shape collection is known as a
<a href="https://tools.ietf.org/html/rfc7946#section-3.1.8">GeometryCollection</a>
diff --git a/platform/darwin/src/MGLShapeSource.h b/platform/darwin/src/MGLShapeSource.h
index 929609e91f..6fa93476be 100644
--- a/platform/darwin/src/MGLShapeSource.h
+++ b/platform/darwin/src/MGLShapeSource.h
@@ -1,12 +1,99 @@
-#import "MGLAbstractShapeSource.h"
-
#import "MGLFoundation.h"
#import "MGLTypes.h"
-#import "MGLShape.h"
+#import "MGLSource.h"
NS_ASSUME_NONNULL_BEGIN
@protocol MGLFeature;
+@class MGLShape;
+
+/**
+ Options for `MGLShapeSource` objects.
+ */
+typedef NSString *MGLShapeSourceOption NS_STRING_ENUM;
+
+/**
+ An `NSNumber` object containing a Boolean enabling or disabling clustering.
+ If the `shape` property contains point shapes, setting this option to
+ `YES` clusters the points by radius into groups. The default value is `NO`.
+
+ This option corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-cluster"><code>cluster</code></a>
+ source property in the Mapbox Style Specification.
+
+ This option only affects point features within an `MGLShapeSource` object; it
+ is ignored when creating an `MGLComputedShapeSource` object.
+ */
+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.
+
+ This option only affects point features within an `MGLShapeSource` object; it
+ is ignored when creating an `MGLComputedShapeSource` object.
+ */
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius;
+
+/**
+ An `NSNumber` object containing an integer; specifies the maximum zoom level at
+ which to cluster points if clustering is enabled. Defaults to one zoom level
+ less than the value of `MGLShapeSourceOptionMaximumZoomLevel` so that, at the
+ maximum zoom level, the shapes are not clustered.
+
+ This option corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-clusterMaxZoom"><code>clusterMaxZoom</code></a>
+ source property in the Mapbox Style Specification.
+
+ This option only affects point features within an `MGLShapeSource` object; it
+ is ignored when creating an `MGLComputedShapeSource` object.
+ */
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering;
+
+/**
+ An `NSNumber` object containing an integer; specifies the minimum zoom level at
+ which to create vector tiles. The default value is 0.
+
+ This option corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson-minzoom"><code>minzoom</code></a>
+ source property in the Mapbox Style Specification.
+ */
+extern MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMinimumZoomLevel;
+
+/**
+ An `NSNumber` object containing an integer; specifies the maximum zoom level at
+ which to create vector tiles. A greater value produces greater detail at high
+ zoom levels. The default value is 18.
+
+ This option corresponds to the
+ <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 MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel;
+
+/**
+ An `NSNumber` object containing an integer; specifies the size of the tile
+ buffer on each side. A value of 0 produces no buffer. A value of 512 produces a
+ buffer as wide as the tile itself. Larger values produce fewer rendering
+ artifacts near tile edges and slower performance. The default value is 128.
+
+ This option corresponds to the
+ <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 MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionBuffer;
+
+/**
+ An `NSNumber` object containing a double; specifies the Douglas-Peucker
+ simplification tolerance. A greater value produces simpler geometries and
+ improves performance. The default value is 0.375.
+
+ This option corresponds to the
+ <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 MGL_EXPORT const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance;
/**
`MGLShapeSource` is a map content source that supplies vector shapes to be
@@ -16,6 +103,10 @@ NS_ASSUME_NONNULL_BEGIN
`MGLStyle` object along with an `MGLVectorStyleLayer` object. The vector style
layer defines the appearance of any content supplied by the shape source. You
can update a shape source by setting its `shape` or `URL` property.
+
+ `MGLShapeSource` is optimized for data sets that change dynamically and fit
+ completely in memory. For large data sets that do not fit completely in memory,
+ use the `MGLComputedShapeSource` or `MGLVectorTileSource` class.
Each
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-geojson"><code>geojson</code></a>
@@ -41,13 +132,21 @@ NS_ASSUME_NONNULL_BEGIN
```
*/
MGL_EXPORT
-@interface MGLShapeSource : MGLAbstractShapeSource
+@interface MGLShapeSource : MGLSource
#pragma mark Initializing a Source
/**
Returns a shape source with an identifier, URL, and dictionary of options for
the source.
+
+ This class supports the following options: `MGLShapeSourceOptionClustered`,
+ `MGLShapeSourceOptionClusterRadius`,
+ `MGLShapeSourceOptionMaximumZoomLevelForClustering`,
+ `MGLShapeSourceOptionMinimumZoomLevel`, `MGLShapeSourceOptionMaximumZoomLevel`,
+ `MGLShapeSourceOptionBuffer`, and
+ `MGLShapeSourceOptionSimplificationTolerance`. Shapes provided by a shape
+ source are not clipped or wrapped automatically.
@param identifier A string that uniquely identifies the source.
@param url An HTTP(S) URL, absolute file URL, or local file URL relative to the
@@ -60,6 +159,14 @@ MGL_EXPORT
/**
Returns a shape source with an identifier, a shape, and dictionary of options
for the source.
+
+ This class supports the following options: `MGLShapeSourceOptionClustered`,
+ `MGLShapeSourceOptionClusterRadius`,
+ `MGLShapeSourceOptionMaximumZoomLevelForClustering`,
+ `MGLShapeSourceOptionMinimumZoomLevel`, `MGLShapeSourceOptionMaximumZoomLevel`,
+ `MGLShapeSourceOptionBuffer`, and
+ `MGLShapeSourceOptionSimplificationTolerance`. Shapes provided by a shape
+ source are not clipped or wrapped automatically.
To specify attributes about the shape, use an instance of an `MGLShape`
subclass that conforms to the `MGLFeature` protocol, such as `MGLPointFeature`.
@@ -81,6 +188,14 @@ MGL_EXPORT
/**
Returns a shape source with an identifier, an array of features, and a dictionary
of options for the source.
+
+ This class supports the following options: `MGLShapeSourceOptionClustered`,
+ `MGLShapeSourceOptionClusterRadius`,
+ `MGLShapeSourceOptionMaximumZoomLevelForClustering`,
+ `MGLShapeSourceOptionMinimumZoomLevel`, `MGLShapeSourceOptionMaximumZoomLevel`,
+ `MGLShapeSourceOptionBuffer`, and
+ `MGLShapeSourceOptionSimplificationTolerance`. Shapes provided by a shape
+ source are not clipped or wrapped automatically.
Unlike `-initWithIdentifier:shapes:options:`, this method accepts `MGLFeature`
instances, such as `MGLPointFeature` objects, whose attributes you can use when
@@ -100,6 +215,14 @@ MGL_EXPORT
/**
Returns a shape source with an identifier, an array of shapes, and a dictionary of
options for the source.
+
+ This class supports the following options: `MGLShapeSourceOptionClustered`,
+ `MGLShapeSourceOptionClusterRadius`,
+ `MGLShapeSourceOptionMaximumZoomLevelForClustering`,
+ `MGLShapeSourceOptionMinimumZoomLevel`, `MGLShapeSourceOptionMaximumZoomLevel`,
+ `MGLShapeSourceOptionBuffer`, and
+ `MGLShapeSourceOptionSimplificationTolerance`. Shapes provided by a shape
+ source are not clipped or wrapped automatically.
Any `MGLFeature` instance passed into this initializer is treated as an ordinary
shape, causing any attributes to be inaccessible to an `MGLVectorStyleLayer` when
diff --git a/platform/darwin/src/MGLShapeSource.mm b/platform/darwin/src/MGLShapeSource.mm
index 8fbb9a18ef..dcc3fd97f5 100644
--- a/platform/darwin/src/MGLShapeSource.mm
+++ b/platform/darwin/src/MGLShapeSource.mm
@@ -1,5 +1,4 @@
#import "MGLShapeSource_Private.h"
-#import "MGLAbstractShapeSource_Private.h"
#import "MGLStyle_Private.h"
#import "MGLMapView_Private.h"
@@ -14,7 +13,75 @@
#include <mbgl/style/sources/geojson_source.hpp>
#include <mbgl/renderer/renderer.hpp>
+const MGLShapeSourceOption MGLShapeSourceOptionBuffer = @"MGLShapeSourceOptionBuffer";
+const MGLShapeSourceOption MGLShapeSourceOptionClusterRadius = @"MGLShapeSourceOptionClusterRadius";
+const MGLShapeSourceOption MGLShapeSourceOptionClustered = @"MGLShapeSourceOptionClustered";
+const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevel = @"MGLShapeSourceOptionMaximumZoomLevel";
+const MGLShapeSourceOption MGLShapeSourceOptionMaximumZoomLevelForClustering = @"MGLShapeSourceOptionMaximumZoomLevelForClustering";
+const MGLShapeSourceOption MGLShapeSourceOptionMinimumZoomLevel = @"MGLShapeSourceOptionMinimumZoomLevel";
+const MGLShapeSourceOption MGLShapeSourceOptionSimplificationTolerance = @"MGLShapeSourceOptionSimplificationTolerance";
+
+mbgl::style::GeoJSONOptions MGLGeoJSONOptionsFromDictionary(NS_DICTIONARY_OF(MGLShapeSourceOption, id) *options) {
+ auto geoJSONOptions = mbgl::style::GeoJSONOptions();
+
+ if (NSNumber *value = options[MGLShapeSourceOptionMinimumZoomLevel]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionMaximumZoomLevel must be an NSNumber."];
+ }
+ geoJSONOptions.minzoom = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevel]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionMaximumZoomLevel must be an NSNumber."];
+ }
+ geoJSONOptions.maxzoom = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionBuffer]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionBuffer must be an NSNumber."];
+ }
+ geoJSONOptions.buffer = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionSimplificationTolerance]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionSimplificationTolerance must be an NSNumber."];
+ }
+ geoJSONOptions.tolerance = value.doubleValue;
+ }
+ if (NSNumber *value = options[MGLShapeSourceOptionClusterRadius]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionClusterRadius must be an NSNumber."];
+ }
+ geoJSONOptions.clusterRadius = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionMaximumZoomLevelForClustering]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionMaximumZoomLevelForClustering must be an NSNumber."];
+ }
+ geoJSONOptions.clusterMaxZoom = value.integerValue;
+ }
+
+ if (NSNumber *value = options[MGLShapeSourceOptionClustered]) {
+ if (![value isKindOfClass:[NSNumber class]]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"MGLShapeSourceOptionClustered must be an NSNumber."];
+ }
+ geoJSONOptions.cluster = value.boolValue;
+ }
+
+ return geoJSONOptions;
+}
@interface MGLShapeSource ()
diff --git a/platform/darwin/src/MGLShapeSource_Private.h b/platform/darwin/src/MGLShapeSource_Private.h
index 1ea2c39b8e..0720074d1d 100644
--- a/platform/darwin/src/MGLShapeSource_Private.h
+++ b/platform/darwin/src/MGLShapeSource_Private.h
@@ -9,7 +9,7 @@ namespace mbgl {
}
}
-@interface MGLShapeSource (Private)
-@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 8d8c936833..7bbf02fa7c 100644
--- a/platform/darwin/src/MGLSource.h
+++ b/platform/darwin/src/MGLSource.h
@@ -16,10 +16,11 @@ NS_ASSUME_NONNULL_BEGIN
add and remove sources dynamically using methods such as
`-[MGLStyle addSource:]` and `-[MGLStyle sourceWithIdentifier:]`.
- Create instances of `MGLShapeSource`, `MGLImageSource` and the concrete subclasses of
- `MGLTileSource` (`MGLVectorSource` and `MGLRasterSource`) in order to use
- `MGLSource`'s properties and methods. Do not create instances of `MGLSource`
- directly, and do not create your own subclasses of this class.
+ Create instances of `MGLShapeSource`, `MGLComputedShapeSource`,
+ `MGLImageSource`, and the concrete subclasses of `MGLTileSource`
+ (`MGLVectorTileSource` and `MGLRasterTileSource`) in order to use `MGLSource`’s
+ properties and methods. Do not create instances of `MGLSource` directly, and do
+ not create your own subclasses of this class.
*/
MGL_EXPORT
@interface MGLSource : NSObject
diff --git a/platform/darwin/src/MGLStyle.h b/platform/darwin/src/MGLStyle.h
index 0b360de8fc..6df627d7af 100644
--- a/platform/darwin/src/MGLStyle.h
+++ b/platform/darwin/src/MGLStyle.h
@@ -68,7 +68,7 @@ MGL_EXPORT
`-streetsStyleURLWithVersion:` method instead. Such details may change
significantly from version to version.
*/
-+ (NSURL *)streetsStyleURL;
+@property (class, nonatomic, readonly) NSURL *streetsStyleURL;
/**
Returns the URL to the given version of the
@@ -83,13 +83,7 @@ MGL_EXPORT
*/
+ (NSURL *)streetsStyleURLWithVersion:(NSInteger)version;
-/**
- Returns the URL to version 8 of the
- <a href="https://www.mapbox.com/blog/emerald-gl/">Mapbox Emerald</a> style.
-
- Emerald is a tactile style with subtle textures and dramatic hillshading.
- */
-+ (NSURL *)emeraldStyleURL __attribute__((deprecated("Create an NSURL object with the string “mapbox://styles/mapbox/emerald-v8”.")));
++ (NSURL *)emeraldStyleURL __attribute__((unavailable("Create an NSURL object with the string “mapbox://styles/mapbox/emerald-v8”.")));
/**
Returns the URL to the current version of the
@@ -104,7 +98,7 @@ MGL_EXPORT
`-outdoorsStyleURLWithVersion:` method instead. Such details may change
significantly from version to version.
*/
-+ (NSURL *)outdoorsStyleURL;
+@property (class, nonatomic, readonly) NSURL *outdoorsStyleURL;
/**
Returns the URL to the given version of the
@@ -128,7 +122,7 @@ MGL_EXPORT
`-lightStyleURLWithVersion:` method instead. Such details may change
significantly from version to version.
*/
-+ (NSURL *)lightStyleURL;
+@property (class, nonatomic, readonly) NSURL *lightStyleURL;
/**
Returns the URL to the given version of the
@@ -153,7 +147,7 @@ MGL_EXPORT
`-darkStyleURLWithVersion:` method instead. Such details may change
significantly from version to version.
*/
-+ (NSURL *)darkStyleURL;
+@property (class, nonatomic, readonly) NSURL *darkStyleURL;
/**
Returns the URL to the given version of the
@@ -178,7 +172,7 @@ MGL_EXPORT
`-satelliteStyleURLWithVersion:` method instead. Such details may change
significantly from version to version.
*/
-+ (NSURL *)satelliteStyleURL;
+@property (class, nonatomic, readonly) NSURL *satelliteStyleURL;
/**
Returns the URL to the given version of the
@@ -191,16 +185,8 @@ MGL_EXPORT
*/
+ (NSURL *)satelliteStyleURLWithVersion:(NSInteger)version;
-/**
- Returns the URL to version 8 of the
- <a href="https://www.mapbox.com/maps/satellite/">Mapbox Satellite Streets</a>
- style.
- Satellite Streets combines the high-resolution satellite and aerial imagery of
- Mapbox Satellite with unobtrusive labels and translucent roads from Mapbox
- Streets.
- */
-+ (NSURL *)hybridStyleURL __attribute__((deprecated("Use -satelliteStreetsStyleURL.")));
++ (NSURL *)hybridStyleURL __attribute__((unavailable("Use -satelliteStreetsStyleURL.")));
/**
Returns the URL to the current version of the
@@ -217,7 +203,7 @@ MGL_EXPORT
`-satelliteStreetsStyleURLWithVersion:` method instead. Such details may
change significantly from version to version.
*/
-+ (NSURL *)satelliteStreetsStyleURL;
+@property (class, nonatomic, readonly) NSURL *satelliteStreetsStyleURL;
/**
Returns the URL to the given version of the
@@ -232,39 +218,14 @@ MGL_EXPORT
*/
+ (NSURL *)satelliteStreetsStyleURLWithVersion:(NSInteger)version;
-/**
- Returns the URL to version 2 of the
- <a href="https://www.mapbox.com/blog/live-traffic-maps/">Mapbox Traffic Day</a>
- style.
- */
-+ (NSURL *)trafficDayStyleURL __attribute__((deprecated("Create an NSURL object with the string “mapbox://styles/mapbox/traffic-day-v2”.")));
-
-/**
- Returns the URL to the given version of the
- <a href="https://www.mapbox.com/blog/live-traffic-maps/">Mapbox Traffic Day</a>
- style as of publication.
-
- @param version A specific version of the style.
- */
-+ (NSURL *)trafficDayStyleURLWithVersion:(NSInteger)version __attribute__((deprecated("Create an NSURL object with the string “mapbox://styles/mapbox/traffic-day-v2”.")));;
++ (NSURL *)trafficDayStyleURL __attribute__((unavailable("Create an NSURL object with the string “mapbox://styles/mapbox/traffic-day-v2”.")));
-/**
- Returns the URL to the version 2 of the
- <a href="https://www.mapbox.com/blog/live-traffic-maps/">Mapbox Traffic Night</a>
- style.
++ (NSURL *)trafficDayStyleURLWithVersion:(NSInteger)version __attribute__((unavailable("Create an NSURL object with the string “mapbox://styles/mapbox/traffic-day-v2”.")));;
- */
-+ (NSURL *)trafficNightStyleURL __attribute__((deprecated("Create an NSURL object with the string “mapbox://styles/mapbox/traffic-night-v2”.")));
++ (NSURL *)trafficNightStyleURL __attribute__((unavailable("Create an NSURL object with the string “mapbox://styles/mapbox/traffic-night-v2”.")));
-/**
- Returns the URL to to the version 2 of the
- <a href="https://www.mapbox.com/blog/live-traffic-maps/">Mapbox Traffic Night</a>
- style as of publication.
-
- @param version A specific version of the style.
- */
-+ (NSURL *)trafficNightStyleURLWithVersion:(NSInteger)version __attribute__((deprecated("Create an NSURL object with the string “mapbox://styles/mapbox/traffic-night-v2”.")));
++ (NSURL *)trafficNightStyleURLWithVersion:(NSInteger)version __attribute__((unavailable("Create an NSURL object with the string “mapbox://styles/mapbox/traffic-night-v2”.")));
#pragma mark Accessing Metadata About the Style
@@ -455,25 +416,14 @@ MGL_EXPORT
#pragma mark Managing Style Classes
-/**
- Support for style classes has been removed. This property always returns an empty array.
- */
-@property (nonatomic) NS_ARRAY_OF(NSString *) *styleClasses __attribute__((deprecated("This property is non-functional.")));
-/**
- Support for style classes has been removed. This method always returns NO.
- */
-- (BOOL)hasStyleClass:(NSString *)styleClass __attribute__((deprecated("This method is non-functional.")));
+@property (nonatomic) NS_ARRAY_OF(NSString *) *styleClasses __attribute__((unavailable("Support for style classes has been removed.")));
-/**
- Support for style classes has been removed. This method is a no-op.
- */
-- (void)addStyleClass:(NSString *)styleClass __attribute__((deprecated("This method is non-functional.")));
+- (BOOL)hasStyleClass:(NSString *)styleClass __attribute__((unavailable("Support for style classes has been removed.")));
-/**
- Support for style classes has been removed. This method is a no-op.
- */
-- (void)removeStyleClass:(NSString *)styleClass __attribute__((deprecated("This method is non-functional.")));
+- (void)addStyleClass:(NSString *)styleClass __attribute__((unavailable("Support for style classes has been removed.")));
+
+- (void)removeStyleClass:(NSString *)styleClass __attribute__((unavailable("Support for style classes has been removed.")));
#pragma mark Managing a Style’s Images
@@ -532,17 +482,22 @@ MGL_EXPORT
#pragma mark Localizing Map Content
/**
- A Boolean value that determines whether the style attempts to localize labels in
- the style into the system’s preferred language.
+ Attempts to localize labels in the style into the given locale.
+
+ This method automatically modifies the text property of any symbol style layer
+ in the style whose source is the
+ <a href="https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview">Mapbox Streets source</a>.
+ On iOS, the user can set the system’s preferred language in Settings, General
+ Settings, Language & Region. On macOS, the user can set the system’s preferred
+ language in the Language & Region pane of System Preferences.
- When this property is enabled, the style automatically modifies the text property
- of any symbol style layer whose source is the
- <a href="https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview">Mapbox
- Streets source</a>. On iOS, the user can set the system’s preferred language in
- Settings, General Settings, Language & Region. On macOS, the user can set the
- system’s preferred language in the Language & Region pane of System Preferences.
- */
-@property (nonatomic) BOOL localizesLabels;
+ @param locale The locale into which labels should be localized. To use the
+ system’s preferred language, if supported, specify `nil`. To use the local
+ language, specify a locale with the identifier `mul`.
+ */
+- (void)localizeLabelsIntoLocale:(nullable NSLocale *)locale;
+
+@property (nonatomic) BOOL localizesLabels __attribute__((unavailable("Use -localizeLabelsIntoLocale: instead.")));
@end
diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm
index f6fc5533be..867ac6c451 100644
--- a/platform/darwin/src/MGLStyle.mm
+++ b/platform/darwin/src/MGLStyle.mm
@@ -18,9 +18,8 @@
#import "MGLSource_Private.h"
#import "MGLLight_Private.h"
#import "MGLTileSource_Private.h"
-#import "MGLVectorSource.h"
-#import "MGLVectorSource_Private.h"
-#import "MGLRasterSource.h"
+#import "MGLVectorTileSource_Private.h"
+#import "MGLRasterTileSource.h"
#import "MGLRasterDEMSource.h"
#import "MGLShapeSource.h"
#import "MGLImageSource.h"
@@ -83,6 +82,7 @@
@property (nonatomic, readonly, weak) MGLMapView *mapView;
@property (nonatomic, readonly) mbgl::style::Style *rawStyle;
@property (readonly, copy, nullable) NSURL *URL;
+@property (nonatomic, readwrite, strong) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLOpenGLStyleLayer *) *openGLLayers;
@property (nonatomic) NS_MUTABLE_DICTIONARY_OF(NSString *, NS_DICTIONARY_OF(NSObject *, MGLTextLanguage *) *) *localizedLayersByIdentifier;
@end
@@ -116,64 +116,16 @@ MGL_DEFINE_STYLE(satelliteStreets, satellite-streets)
// Make sure all the styles listed in mbgl::util::default_styles::orderedStyles
// are defined above and also declared in MGLStyle.h.
-static_assert(8 == mbgl::util::default_styles::numOrderedStyles,
+static_assert(6 == mbgl::util::default_styles::numOrderedStyles,
"mbgl::util::default_styles::orderedStyles and MGLStyle have different numbers of styles.");
-// Hybrid has been renamed Satellite Streets, so the last Hybrid version is hard-coded here.
-static NSURL *MGLStyleURL_hybrid;
-+ (NSURL *)hybridStyleURL {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- MGLStyleURL_hybrid = [NSURL URLWithString:@"mapbox://styles/mapbox/satellite-hybrid-v8"];
- });
- return MGLStyleURL_hybrid;
-}
-
-// Emerald is no longer getting new versions as a default style, so the current version is hard-coded here.
-static NSURL *MGLStyleURL_emerald;
-+ (NSURL *)emeraldStyleURL {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- MGLStyleURL_emerald = [NSURL URLWithString:@"mapbox://styles/mapbox/emerald-v8"];
- });
- return MGLStyleURL_emerald;
-}
-
-// Traffic Day is no longer getting new versions as a default style, so the current version is hard-coded here.
-static NSURL *MGLStyleURL_trafficDay;
-+ (NSURL *)trafficDayStyleURL {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- MGLStyleURL_trafficDay = [NSURL URLWithString:@"mapbox://styles/mapbox/traffic-day-v2"];
- });
- return MGLStyleURL_trafficDay;
-}
-
-+ (NSURL *)trafficDayStyleURLWithVersion:(NSInteger)version {
- return [NSURL URLWithString:[@"mapbox://styles/mapbox/traffic-day-v" stringByAppendingFormat:@"%li", (long)version]];
-}
-
-// Traffic Night is no longer getting new versions as a default style, so the current version is hard-coded here.
-static NSURL *MGLStyleURL_trafficNight;
-+ (NSURL *)trafficNightStyleURL {
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- MGLStyleURL_trafficNight = [NSURL URLWithString:@"mapbox://styles/mapbox/traffic-night-v2"];
- });
- return MGLStyleURL_trafficNight;
-}
-
-+ (NSURL *)trafficNightStyleURLWithVersion:(NSInteger)version {
- return [NSURL URLWithString:[@"mapbox://styles/mapbox/traffic-night-v" stringByAppendingFormat:@"%li", (long)version]];
-}
-
-
#pragma mark -
- (instancetype)initWithRawStyle:(mbgl::style::Style *)rawStyle mapView:(MGLMapView *)mapView {
if (self = [super init]) {
_mapView = mapView;
_rawStyle = rawStyle;
+ _openGLLayers = [NSMutableDictionary dictionary];
_localizedLayersByIdentifier = [NSMutableDictionary dictionary];
}
return self;
@@ -232,11 +184,11 @@ static NSURL *MGLStyleURL_trafficNight;
// TODO: Fill in options specific to the respective source classes
// https://github.com/mapbox/mapbox-gl-native/issues/6584
if (auto vectorSource = rawSource->as<mbgl::style::VectorSource>()) {
- return [[MGLVectorSource alloc] initWithRawSource:vectorSource mapView:self.mapView];
+ return [[MGLVectorTileSource alloc] initWithRawSource:vectorSource mapView:self.mapView];
} else if (auto geoJSONSource = rawSource->as<mbgl::style::GeoJSONSource>()) {
return [[MGLShapeSource alloc] initWithRawSource:geoJSONSource mapView:self.mapView];
} else if (auto rasterSource = rawSource->as<mbgl::style::RasterSource>()) {
- return [[MGLRasterSource alloc] initWithRawSource:rasterSource mapView:self.mapView];
+ return [[MGLRasterTileSource alloc] initWithRawSource:rasterSource mapView:self.mapView];
} else if (auto rasterDEMSource = rawSource->as<mbgl::style::RasterDEMSource>()) {
return [[MGLRasterDEMSource alloc] initWithRawSource:rasterDEMSource mapView:self.mapView];
} else if (auto imageSource = rawSource->as<mbgl::style::ImageSource>()) {
@@ -534,38 +486,6 @@ static NSURL *MGLStyleURL_trafficNight;
[self didChangeValueForKey:@"layers"];
}
-#pragma mark Style classes
-
-- (NS_ARRAY_OF(NSString *) *)styleClasses
-{
- return @[];
-}
-
-- (void)setStyleClasses:(NS_ARRAY_OF(NSString *) *)appliedClasses
-{
-}
-
-- (void)setStyleClasses:(NS_ARRAY_OF(NSString *) *)appliedClasses transitionDuration:(NSTimeInterval)transitionDuration
-{
-}
-
-- (NSUInteger)countOfStyleClasses {
- return 0;
-}
-
-- (BOOL)hasStyleClass:(NSString *)styleClass
-{
- return NO;
-}
-
-- (void)addStyleClass:(NSString *)styleClass
-{
-}
-
-- (void)removeStyleClass:(NSString *)styleClass
-{
-}
-
#pragma mark Style images
- (void)setImage:(MGLImage *)image forName:(NSString *)name
@@ -650,79 +570,33 @@ static NSURL *MGLStyleURL_trafficNight;
#pragma mark Mapbox Streets source introspection
-- (void)setLocalizesLabels:(BOOL)localizesLabels
-{
- if (_localizesLabels != localizesLabels) {
- _localizesLabels = localizesLabels;
- } else {
- return;
- }
+- (void)localizeLabelsIntoLocale:(nullable NSLocale *)locale {
+ NSSet<MGLVectorTileSource *> *streetsSources =
+ [self.sources filteredSetUsingPredicate:
+ [NSPredicate predicateWithBlock:^BOOL(MGLVectorTileSource * _Nullable source, NSDictionary<NSString *, id> * _Nullable bindings) {
+ return [source isKindOfClass:[MGLVectorTileSource class]] && [source isMapboxStreets];
+ }]];
+ NSSet<NSString *> *streetsSourceIdentifiers = [streetsSources valueForKey:@"identifier"];
- if (_localizesLabels) {
- NSString *preferredLanguage = [MGLVectorSource preferredMapboxStreetsLanguage];
- NSMutableDictionary *localizedKeysByKeyBySourceIdentifier = [NSMutableDictionary dictionary];
- for (MGLSymbolStyleLayer *layer in self.layers) {
- if (![layer isKindOfClass:[MGLSymbolStyleLayer class]]) {
- continue;
- }
-
- MGLVectorSource *source = (MGLVectorSource *)[self sourceWithIdentifier:layer.sourceIdentifier];
- if (![source isKindOfClass:[MGLVectorSource class]] || !source.mapboxStreets) {
- continue;
- }
-
- NSDictionary *localizedKeysByKey = localizedKeysByKeyBySourceIdentifier[layer.sourceIdentifier];
- if (!localizedKeysByKey) {
- localizedKeysByKey = localizedKeysByKeyBySourceIdentifier[layer.sourceIdentifier] = [source localizedKeysByKeyForPreferredLanguage:preferredLanguage];
- }
-
- NSString *(^stringByLocalizingString)(NSString *) = ^ NSString * (NSString *string) {
- NSMutableString *localizedString = string.mutableCopy;
- [localizedKeysByKey enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull localizedKey, BOOL * _Nonnull stop) {
- NSAssert([key isKindOfClass:[NSString class]], @"key is not a string");
- NSAssert([localizedKey isKindOfClass:[NSString class]], @"localizedKey is not a string");
- [localizedString replaceOccurrencesOfString:[NSString stringWithFormat:@"{%@}", key]
- withString:[NSString stringWithFormat:@"{%@}", localizedKey]
- options:0
- range:NSMakeRange(0, localizedString.length)];
- }];
- return localizedString;
- };
-
- if (layer.text.expressionType == NSConstantValueExpressionType) {
- NSString *textField = layer.text.constantValue;
- NSString *localizingString = stringByLocalizingString(textField);
- if (![textField isEqualToString:localizingString]) {
- MGLTextLanguage *textLanguage = [[MGLTextLanguage alloc] initWithTextLanguage:textField
- updatedTextField:localizingString];
- [self.localizedLayersByIdentifier setObject:@{ textField : textLanguage } forKey:layer.identifier];
- layer.text = [NSExpression expressionForConstantValue:localizingString];
- }
- }
+ for (MGLSymbolStyleLayer *layer in self.layers) {
+ if (![layer isKindOfClass:[MGLSymbolStyleLayer class]]) {
+ continue;
+ }
+ if (![streetsSourceIdentifiers containsObject:layer.sourceIdentifier]) {
+ continue;
}
- } else {
- [self.localizedLayersByIdentifier enumerateKeysAndObjectsUsingBlock:^(NSString *identifier, NSDictionary<NSObject *, MGLTextLanguage *> *textFields, BOOL *done) {
- MGLSymbolStyleLayer *layer = (MGLSymbolStyleLayer *)[self.mapView.style layerWithIdentifier:identifier];
-
- if (layer.text.expressionType == NSConstantValueExpressionType) {
- NSString *textField = layer.text.constantValue;
- [textFields enumerateKeysAndObjectsUsingBlock:^(NSObject *originalLanguage, MGLTextLanguage *textLanguage, BOOL *done) {
- if ([textLanguage.updatedTextField isEqualToString:textField]) {
- layer.text = [NSExpression expressionForConstantValue:textLanguage.originalTextField];
- }
- }];
-
- }
- }];
-
- self.localizedLayersByIdentifier = [NSMutableDictionary dictionary];
+ NSExpression *text = layer.text;
+ NSExpression *localizedText = [text mgl_expressionLocalizedIntoLocale:locale];
+ if (![localizedText isEqual:text]) {
+ layer.text = localizedText;
+ }
}
}
-- (NS_SET_OF(MGLVectorSource *) *)mapboxStreetsSources {
- return [self.sources objectsPassingTest:^BOOL (__kindof MGLVectorSource * _Nonnull source, BOOL * _Nonnull stop) {
- return [source isKindOfClass:[MGLVectorSource class]] && source.mapboxStreets;
+- (NS_SET_OF(MGLVectorTileSource *) *)mapboxStreetsSources {
+ return [self.sources objectsPassingTest:^BOOL (__kindof MGLVectorTileSource * _Nonnull source, BOOL * _Nonnull stop) {
+ return [source isKindOfClass:[MGLVectorTileSource class]] && source.mapboxStreets;
}];
}
diff --git a/platform/darwin/src/MGLStyleLayer.mm.ejs b/platform/darwin/src/MGLStyleLayer.mm.ejs
index ac7676a1cc..42940083b5 100644
--- a/platform/darwin/src/MGLStyleLayer.mm.ejs
+++ b/platform/darwin/src/MGLStyleLayer.mm.ejs
@@ -136,7 +136,12 @@ namespace mbgl {
if (propertyValue.isUndefined()) {
propertyValue = self.rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>();
}
+<% if (property.type === 'string') { -%>
+ NSExpression *expression = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toExpression(propertyValue);
+ return expression.mgl_expressionByReplacingTokensWithKeyPaths;
+<% } else { -%>
return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toExpression(propertyValue);
+<% } -%>
}
<% if (property.original) { -%>
@@ -174,7 +179,12 @@ namespace mbgl {
if (propertyValue.isUndefined()) {
propertyValue = self.rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>();
}
+<% if (property.type === 'string') { -%>
+ NSExpression *expression = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toExpression(propertyValue);
+ return expression.mgl_expressionByReplacingTokensWithKeyPaths;
+<% } else { -%>
return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toExpression(propertyValue);
+<% } -%>
}
<% if (property["transition"]) { -%>
diff --git a/platform/darwin/src/MGLStyleValue.h b/platform/darwin/src/MGLStyleValue.h
index f6e9c51729..65f89c5909 100644
--- a/platform/darwin/src/MGLStyleValue.h
+++ b/platform/darwin/src/MGLStyleValue.h
@@ -8,13 +8,13 @@ NS_ASSUME_NONNULL_BEGIN
typedef NSString *MGLStyleFunctionOption NS_STRING_ENUM NS_UNAVAILABLE;
-extern MGL_EXPORT const MGLStyleFunctionOption MGLStyleFunctionOptionInterpolationBase __attribute__((unavailable("Use NSExpression instead, applying the mgl_interpolateWithCurveType:parameters:stops: function with a curve type of “exponential” and a non-nil parameter.")));
+extern MGL_EXPORT const MGLStyleFunctionOption MGLStyleFunctionOptionInterpolationBase __attribute__((unavailable("Use NSExpression instead, applying the mgl_interpolate:withCurveType:parameters:stops: function with a curve type of “exponential” and a non-nil parameter.")));
extern MGL_EXPORT const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue __attribute__((unavailable("Use +[NSExpression expressionForConditional:trueExpression:falseExpression:] instead.")));
typedef NS_ENUM(NSUInteger, MGLInterpolationMode) {
- MGLInterpolationModeExponential __attribute__((unavailable("Use NSExpression instead, applying the mgl_interpolateWithCurveType:parameters:stops: function with a curve type of “exponential”."))) = 0,
- MGLInterpolationModeInterval __attribute__((unavailable("Use NSExpression instead, calling the mgl_stepWithMinimum:stops: function."))),
+ MGLInterpolationModeExponential __attribute__((unavailable("Use NSExpression instead, applying the mgl_interpolate:withCurveType:parameters:stops: function with a curve type of “exponential”."))) = 0,
+ MGLInterpolationModeInterval __attribute__((unavailable("Use NSExpression instead, calling the mgl_step:from:stops: function."))),
MGLInterpolationModeCategorical __attribute__((unavailable("Use NSExpression instead."))),
MGLInterpolationModeIdentity __attribute__((unavailable("Use +[NSExpression expressionForKeyPath:] instead.")))
} __attribute__((unavailable("Use NSExpression instead.")));
@@ -29,19 +29,19 @@ MGL_EXPORT __attribute__((unavailable("Use +[NSExpression expressionForConstantV
@compatibility_alias MGLStyleConstantValue MGLConstantStyleValue;
-MGL_EXPORT __attribute__((unavailable("Use NSExpression instead, calling the mgl_stepWithMinimum:stops: or mgl_interpolateWithCurveType:parameters:stops: function.")))
+MGL_EXPORT __attribute__((unavailable("Use NSExpression instead, calling the mgl_step:from:stops: or mgl_interpolate:withCurveType:parameters:stops: function.")))
@interface MGLStyleFunction<T> : MGLStyleValue<T>
@end
-MGL_EXPORT __attribute__((unavailable("Use NSExpression instead, applying the mgl_stepWithMinimum:stops: or mgl_interpolateWithCurveType:parameters:stops: function to the $zoomLevel variable.")))
+MGL_EXPORT __attribute__((unavailable("Use NSExpression instead, applying the mgl_step:from:stops: or mgl_interpolate:withCurveType:parameters:stops: function to the $zoomLevel variable.")))
@interface MGLCameraStyleFunction<T> : MGLStyleFunction<T>
@end
-MGL_EXPORT __attribute__((unavailable("Use NSExpression instead, applying the mgl_stepWithMinimum:stops: or mgl_interpolateWithCurveType:parameters:stops: function to a key path expression.")))
+MGL_EXPORT __attribute__((unavailable("Use NSExpression instead, applying the mgl_step:from:stops: or mgl_interpolate:withCurveType:parameters:stops: function to a key path expression.")))
@interface MGLSourceStyleFunction<T> : MGLStyleFunction<T>
@end
-MGL_EXPORT __attribute__((unavailable("Use a NSExpression instead with nested mgl_stepWithMinimum:stops: or mgl_interpolateWithCurveType:parameters:stops: function calls.")))
+MGL_EXPORT __attribute__((unavailable("Use a NSExpression instead with nested mgl_step:from:stops: or mgl_interpolate:withCurveType:parameters:stops: function calls.")))
@interface MGLCompositeStyleFunction<T> : MGLStyleFunction<T>
@end
diff --git a/platform/darwin/src/MGLStyleValue.mm b/platform/darwin/src/MGLStyleValue.mm
index 74e1926f79..5103b5f5cf 100644
--- a/platform/darwin/src/MGLStyleValue.mm
+++ b/platform/darwin/src/MGLStyleValue.mm
@@ -5,7 +5,7 @@
const MGLStyleFunctionOption MGLStyleFunctionOptionInterpolationBase = @"MGLStyleFunctionOptionInterpolationBase";
const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunctionOptionDefaultValue";
-id MGLJSONObjectFromMBGLValue(const mbgl::style::expression::Value &value) {
+id MGLJSONObjectFromMBGLValue(const mbgl::Value &value) {
return value.match([](const mbgl::NullValue) -> id {
return [NSNull null];
}, [](const bool value) {
@@ -24,98 +24,23 @@ id MGLJSONObjectFromMBGLValue(const mbgl::style::expression::Value &value) {
std::array<float, 3> spherical = value.getSpherical();
MGLSphericalPosition position = MGLSphericalPositionMake(spherical[0], spherical[1], spherical[2]);
return [NSValue valueWithMGLSphericalPosition:position];
- }, [&](const std::vector<mbgl::style::expression::Value> &vector) {
+ }, [&](const std::vector<mbgl::Value> &vector) {
NSMutableArray *array = [NSMutableArray arrayWithCapacity:vector.size()];
for (auto value : vector) {
[array addObject:MGLJSONObjectFromMBGLValue(value)];
}
- return @[@"literal", array];
- }, [&](const std::unordered_map<std::string, mbgl::style::expression::Value> &map) {
+ return array;
+ }, [&](const std::unordered_map<std::string, mbgl::Value> &map) {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:map.size()];
for (auto &item : map) {
dictionary[@(item.first.c_str())] = MGLJSONObjectFromMBGLValue(item.second);
}
- return @[@"literal", dictionary];
+ return dictionary;
}, [](const auto &) -> id {
return nil;
});
}
id MGLJSONObjectFromMBGLExpression(const mbgl::style::expression::Expression &mbglExpression) {
- using namespace mbgl::style::expression;
- if (auto literalExpression = dynamic_cast<const Literal *>(&mbglExpression)) {
- auto result = literalExpression->evaluate({ nullptr });
- return result ? MGLJSONObjectFromMBGLValue(*result) : nil;
- }
- if (auto assertExpression = dynamic_cast<const ArrayAssertion *>(&mbglExpression)) {
- NSMutableArray *inputs = [NSMutableArray array];
- assertExpression->eachChild([&](const Expression &child) {
- [inputs addObject:MGLJSONObjectFromMBGLExpression(child)];
- });
- return @[@"literal", inputs.lastObject];
- }
- if (auto assertExpression = dynamic_cast<const Assertion *>(&mbglExpression)) {
- NSMutableArray *inputs = [NSMutableArray array];
- assertExpression->eachChild([&](const Expression &child) {
- [inputs addObject:MGLJSONObjectFromMBGLExpression(child)];
- });
- return inputs.firstObject;
- }
- if (auto compoundExpression = dynamic_cast<const CompoundExpressionBase *>(&mbglExpression)) {
- const std::string name = compoundExpression->getName();
- mbgl::optional<std::size_t> parameterCount = compoundExpression->getParameterCount();
- NSMutableArray *expressionObject = parameterCount ? [NSMutableArray arrayWithCapacity:*parameterCount + 1] : [NSMutableArray array];
- [expressionObject addObject:@(name.c_str())];
- compoundExpression->eachChild([&](const Expression &child) {
- [expressionObject addObject:MGLJSONObjectFromMBGLExpression(child)];
- });
- return expressionObject;
- }
- if (auto stepExpression = dynamic_cast<const Step *>(&mbglExpression)) {
- auto &input = stepExpression->getInput();
- NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"step", MGLJSONObjectFromMBGLExpression(*input.get()), nil];
- stepExpression->eachStop([&](double stop, const Expression &child) {
- [expressionObject addObject:@(stop)];
- [expressionObject addObject:MGLJSONObjectFromMBGLExpression(child)];
- });
- if ([expressionObject[2] isEqual:@(-INFINITY)]) {
- [expressionObject removeObjectAtIndex:2];
- }
- return expressionObject;
- }
- if (auto interpolateExpression = dynamic_cast<const InterpolateBase *>(&mbglExpression)) {
- auto &interpolator = interpolateExpression->getInterpolator();
- auto &input = interpolateExpression->getInput();
- NSArray *interpolatorObject;
- if (interpolator.is<ExponentialInterpolator>()) {
- auto exponentialInterpolator = interpolator.get<ExponentialInterpolator>();
- interpolatorObject = exponentialInterpolator.base == 1 ? @[@"linear"] : @[@"exponential", @(exponentialInterpolator.base)];
- } else if (interpolator.is<CubicBezierInterpolator>()) {
- auto cubicBezierInterpolator = interpolator.get<CubicBezierInterpolator>();
- auto bezier = cubicBezierInterpolator.ub;
- interpolatorObject = @[
- @"cubic-bezier",
- @(bezier.getP1().first), @(bezier.getP1().second),
- @(bezier.getP2().first), @(bezier.getP2().second),
- ];
- } else {
- NSCAssert(NO, @"Unrecognized interpolator type.");
- }
- NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"interpolate", interpolatorObject, MGLJSONObjectFromMBGLExpression(*input.get()), nil];
- interpolateExpression->eachStop([&](double stop, const Expression &child) {
- [expressionObject addObject:@(stop)];
- [expressionObject addObject:MGLJSONObjectFromMBGLExpression(child)];
- });
- return expressionObject;
- }
- if (auto caseExpression = dynamic_cast<const Case *>(&mbglExpression)) {
- NSMutableArray *expressionObject = [NSMutableArray arrayWithObject:@"case"];
- caseExpression->eachChild([&](const Expression &child) {
- [expressionObject addObject:MGLJSONObjectFromMBGLExpression(child)];
- });
- return expressionObject;
- }
- NSCAssert(NO, @"Unrecognized expression type.");
- return nil;
+ return MGLJSONObjectFromMBGLValue(mbglExpression.serialize());
}
-
diff --git a/platform/darwin/src/MGLStyleValue_Private.h b/platform/darwin/src/MGLStyleValue_Private.h
index 5124c29a90..cc63793d0d 100644
--- a/platform/darwin/src/MGLStyleValue_Private.h
+++ b/platform/darwin/src/MGLStyleValue_Private.h
@@ -58,7 +58,7 @@ public:
if (mbglValue.isUndefined()) {
return nil;
}
- return [NSExpression mgl_expressionWithJSONObject:MGLJSONObjectFromMBGLExpression(mbglValue.getExpression())];
+ return [NSExpression expressionWithMGLJSONObject:MGLJSONObjectFromMBGLExpression(mbglValue.getExpression())];
}
/**
@@ -333,15 +333,15 @@ private: // Private utilities for converting from mbgl to mgl values
}
NSExpression *operator()(const mbgl::style::CameraFunction<MBGLType> &mbglValue) const {
- return [NSExpression mgl_expressionWithJSONObject:MGLJSONObjectFromMBGLExpression(mbglValue.getExpression())];
+ return [NSExpression expressionWithMGLJSONObject:MGLJSONObjectFromMBGLExpression(mbglValue.getExpression())];
}
NSExpression *operator()(const mbgl::style::SourceFunction<MBGLType> &mbglValue) const {
- return [NSExpression mgl_expressionWithJSONObject:MGLJSONObjectFromMBGLExpression(mbglValue.getExpression())];
+ return [NSExpression expressionWithMGLJSONObject:MGLJSONObjectFromMBGLExpression(mbglValue.getExpression())];
}
NSExpression *operator()(const mbgl::style::CompositeFunction<MBGLType> &mbglValue) const {
- return [NSExpression mgl_expressionWithJSONObject:MGLJSONObjectFromMBGLExpression(mbglValue.getExpression())];
+ return [NSExpression expressionWithMGLJSONObject:MGLJSONObjectFromMBGLExpression(mbglValue.getExpression())];
}
};
};
diff --git a/platform/darwin/src/MGLStyle_Private.h b/platform/darwin/src/MGLStyle_Private.h
index 4cbe953a44..24466b8018 100644
--- a/platform/darwin/src/MGLStyle_Private.h
+++ b/platform/darwin/src/MGLStyle_Private.h
@@ -14,7 +14,7 @@ namespace mbgl {
@class MGLAttributionInfo;
@class MGLMapView;
@class MGLOpenGLStyleLayer;
-@class MGLVectorSource;
+@class MGLVectorTileSource;
@class MGLVectorStyleLayer;
@interface MGLStyle (Private)
@@ -25,7 +25,7 @@ namespace mbgl {
@property (nonatomic, readonly) mbgl::style::Style *rawStyle;
- (nullable NS_ARRAY_OF(MGLAttributionInfo *) *)attributionInfosWithFontSize:(CGFloat)fontSize linkColor:(nullable MGLColor *)linkColor;
-
+@property (nonatomic, readonly, strong) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLOpenGLStyleLayer *) *openGLLayers;
- (void)setStyleClasses:(NS_ARRAY_OF(NSString *) *)appliedClasses transitionDuration:(NSTimeInterval)transitionDuration;
@end
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h
index 1017db5442..e27f039b75 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.h
+++ b/platform/darwin/src/MGLSymbolStyleLayer.h
@@ -319,9 +319,10 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslationAnchor) {
An `MGLSymbolStyleLayer` is a style layer that renders icon and text labels at
points or along lines on the map.
- Use a symbol style layer to configure the visual appearance of labels for
- features in vector tiles loaded by an `MGLVectorSource` object or `MGLShape` or
- `MGLFeature` instances in an `MGLShapeSource` object.
+ Use a symbol style layer to configure the visual appearance of feature labels.
+ These features can come from vector tiles loaded by an `MGLVectorTileSource`
+ object, or they can be `MGLShape` or `MGLFeature` instances in an
+ `MGLShapeSource` or `MGLComputedShapeSource` object.
You can access an existing symbol style layer using the
`-[MGLStyle layerWithIdentifier:]` method if you know its identifier;
@@ -460,11 +461,15 @@ MGL_EXPORT
@property (nonatomic, null_resettable) NSExpression *iconIgnorePlacement __attribute__((unavailable("Use iconIgnoresPlacement instead.")));
/**
- Name of image in sprite to use for drawing an image background. Within literal
- values, attribute names enclosed in curly brackets (e.g. `{token}`) are
- replaced with the value of the named attribute. Expressions do not support this
- syntax; for equivalent functionality in expressions, use
- `stringByAppendingString:` and key path expressions.
+ Name of a style image to use for drawing an image background.
+
+ Use the `+[MGLStyle setImage:forName:]` method to associate an image with a
+ name that you can set this property to.
+
+ Within a constant string value, a feature attribute name enclosed in curly
+ braces (e.g., `{token}`) is replaced with the value of the named attribute.
+ Tokens inside non-constant expressions are ignored; instead, use `mgl_join:`
+ and key path expressions.
This attribute corresponds to the <a
href="https://www.mapbox.com/mapbox-gl-style-spec/#layout-symbol-icon-image"><code>icon-image</code></a>
@@ -559,14 +564,14 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `2`. Set this property to `nil` to reset it to the default value.
+ 2. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -610,7 +615,7 @@ MGL_EXPORT
This property is measured in degrees.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
@@ -673,7 +678,7 @@ MGL_EXPORT
This property is measured in factor of the original icon sizes.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
@@ -684,7 +689,7 @@ MGL_EXPORT
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -853,7 +858,7 @@ MGL_EXPORT
This property is measured in degrees.
The default value of this property is an expression that evaluates to the float
- `45`. Set this property to `nil` to reset it to the default value.
+ 45. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `text` is non-`nil`, and
`symbolPlacement` is set to an expression that evaluates to `line`. Otherwise,
@@ -885,7 +890,7 @@ MGL_EXPORT
This property is measured in ems.
The default value of this property is an expression that evaluates to the float
- `10`. Set this property to `nil` to reset it to the default value.
+ 10. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
@@ -896,7 +901,7 @@ MGL_EXPORT
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -968,14 +973,14 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `250`. Set this property to `nil` to reset it to the default value.
+ 250. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `symbolPlacement` is set to an
expression that evaluates to `line`. Otherwise, it is ignored.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 1
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -987,10 +992,12 @@ MGL_EXPORT
@property (nonatomic, null_resettable) NSExpression *symbolSpacing;
/**
- Value to use for a text label. Within literal values, attribute names enclosed
- in curly brackets (e.g. `{token}`) are replaced with the value of the named
- attribute. Expressions do not support this syntax; for equivalent functionality
- in expressions, use `stringByAppendingString:` and key path expressions.
+ Value to use for a text label.
+
+ Within a constant string value, a feature attribute name enclosed in curly
+ braces (e.g., `{token}`) is replaced with the value of the named attribute.
+ Tokens inside non-constant expressions are ignored; instead, use `mgl_join:`
+ and key path expressions.
The default value of this property is an expression that evaluates to the empty
string. Set this property to `nil` to reset it to the default value.
@@ -1122,7 +1129,7 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `16`. Set this property to `nil` to reset it to the default value.
+ 16. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
@@ -1133,7 +1140,7 @@ MGL_EXPORT
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -1212,7 +1219,7 @@ MGL_EXPORT
This property is measured in ems.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
@@ -1234,7 +1241,7 @@ MGL_EXPORT
This property is measured in ems.
The default value of this property is an expression that evaluates to the float
- `1.2`. Set this property to `nil` to reset it to the default value.
+ 1.2. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
@@ -1331,14 +1338,14 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `2`. Set this property to `nil` to reset it to the default value.
+ 2. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -1382,7 +1389,7 @@ MGL_EXPORT
This property is measured in degrees.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
@@ -1463,6 +1470,7 @@ MGL_EXPORT
#pragma mark - Accessing the Paint Attributes
+#if TARGET_OS_IPHONE
/**
The tint color to apply to the icon. The `iconImageName` property must be set
to a template image.
@@ -1484,6 +1492,29 @@ MGL_EXPORT
feature attributes
*/
@property (nonatomic, null_resettable) NSExpression *iconColor;
+#else
+/**
+ The tint color to apply to the icon. The `iconImageName` property must be set
+ to a template image.
+
+ The default value of this property is an expression that evaluates to
+ `NSColor.blackColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ This property is only applied to the style if `iconImageName` is non-`nil`.
+ Otherwise, it is ignored.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable and/or
+ feature attributes
+ */
+@property (nonatomic, null_resettable) NSExpression *iconColor;
+#endif
/**
The transition affecting any changes to this layer’s `iconColor` property.
@@ -1498,14 +1529,14 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -1521,6 +1552,7 @@ MGL_EXPORT
*/
@property (nonatomic) MGLTransition iconHaloBlurTransition;
+#if TARGET_OS_IPHONE
/**
The color of the icon’s halo. The `iconImageName` property must be set to a
template image.
@@ -1542,6 +1574,29 @@ MGL_EXPORT
feature attributes
*/
@property (nonatomic, null_resettable) NSExpression *iconHaloColor;
+#else
+/**
+ The color of the icon’s halo. The `iconImageName` property must be set to a
+ template image.
+
+ The default value of this property is an expression that evaluates to
+ `NSColor.clearColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ This property is only applied to the style if `iconImageName` is non-`nil`.
+ Otherwise, it is ignored.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable and/or
+ feature attributes
+ */
+@property (nonatomic, null_resettable) NSExpression *iconHaloColor;
+#endif
/**
The transition affecting any changes to this layer’s `iconHaloColor` property.
@@ -1556,14 +1611,14 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -1583,14 +1638,14 @@ MGL_EXPORT
The opacity at which the icon will be drawn.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `iconImageName` is non-`nil`.
Otherwise, it is ignored.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -1707,6 +1762,7 @@ MGL_EXPORT
@property (nonatomic, null_resettable) NSExpression *iconTranslateAnchor __attribute__((unavailable("Use iconTranslationAnchor instead.")));
+#if TARGET_OS_IPHONE
/**
The color with which the text will be drawn.
@@ -1727,6 +1783,28 @@ MGL_EXPORT
feature attributes
*/
@property (nonatomic, null_resettable) NSExpression *textColor;
+#else
+/**
+ The color with which the text will be drawn.
+
+ The default value of this property is an expression that evaluates to
+ `NSColor.blackColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ This property is only applied to the style if `text` is non-`nil`. Otherwise,
+ it is ignored.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable and/or
+ feature attributes
+ */
+@property (nonatomic, null_resettable) NSExpression *textColor;
+#endif
/**
The transition affecting any changes to this layer’s `textColor` property.
@@ -1741,14 +1819,14 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -1764,6 +1842,7 @@ MGL_EXPORT
*/
@property (nonatomic) MGLTransition textHaloBlurTransition;
+#if TARGET_OS_IPHONE
/**
The color of the text's halo, which helps it stand out from backgrounds.
@@ -1784,6 +1863,28 @@ MGL_EXPORT
feature attributes
*/
@property (nonatomic, null_resettable) NSExpression *textHaloColor;
+#else
+/**
+ The color of the text's halo, which helps it stand out from backgrounds.
+
+ The default value of this property is an expression that evaluates to
+ `NSColor.clearColor`. Set this property to `nil` to reset it to the default
+ value.
+
+ This property is only applied to the style if `text` is non-`nil`. Otherwise,
+ it is ignored.
+
+ You can set this property to an expression containing any of the following:
+
+ * Constant `NSColor` values
+ * Predefined functions, including mathematical and string operators
+ * Conditional expressions
+ * Variable assignments and references to assigned variables
+ * Interpolation and step functions applied to the `$zoomLevel` variable and/or
+ feature attributes
+ */
+@property (nonatomic, null_resettable) NSExpression *textHaloColor;
+#endif
/**
The transition affecting any changes to this layer’s `textHaloColor` property.
@@ -1799,14 +1900,14 @@ MGL_EXPORT
This property is measured in points.
The default value of this property is an expression that evaluates to the float
- `0`. Set this property to `nil` to reset it to the default value.
+ 0. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values no less than 0
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
@@ -1826,14 +1927,14 @@ MGL_EXPORT
The opacity at which the text will be drawn.
The default value of this property is an expression that evaluates to the float
- `1`. Set this property to `nil` to reset it to the default value.
+ 1. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `text` is non-`nil`. Otherwise,
it is ignored.
You can set this property to an expression containing any of the following:
- * Constant numeric values
+ * Constant numeric values between 0 and 1 inclusive
* Predefined functions, including mathematical and string operators
* Conditional expressions
* Variable assignments and references to assigned variables
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm
index 24d6643e6c..0d9fac4808 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.mm
+++ b/platform/darwin/src/MGLSymbolStyleLayer.mm
@@ -233,7 +233,8 @@ namespace mbgl {
if (propertyValue.isUndefined()) {
propertyValue = self.rawLayer->getDefaultIconImage();
}
- return MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ NSExpression *expression = MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ return expression.mgl_expressionByReplacingTokensWithKeyPaths;
}
- (void)setIconImage:(NSExpression *)iconImage {
@@ -578,7 +579,8 @@ namespace mbgl {
if (propertyValue.isUndefined()) {
propertyValue = self.rawLayer->getDefaultTextField();
}
- return MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ NSExpression *expression = MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
+ return expression.mgl_expressionByReplacingTokensWithKeyPaths;
}
- (void)setTextField:(NSExpression *)textField {
diff --git a/platform/darwin/src/MGLTileSource.h b/platform/darwin/src/MGLTileSource.h
index 2d75fa14d8..4bf09026f2 100644
--- a/platform/darwin/src/MGLTileSource.h
+++ b/platform/darwin/src/MGLTileSource.h
@@ -184,9 +184,9 @@ typedef NS_ENUM(NSUInteger, MGLDEMEncoding) {
Mapbox-hosted tile set, view it in
<a href="https://www.mapbox.com/studio/tilesets/">Mapbox Studio’s Tilesets editor</a>.
- Create instances of `MGLRasterSource` and `MGLVectorSource` in order to use
- `MGLTileSource`'s properties and methods. Do not create instances of `MGLTileSource`
- directly, and do not create your own subclasses of this class.
+ Create instances of `MGLRasterTileSource` and `MGLVectorTileSource` in order
+ to use `MGLTileSource`'s properties and methods. Do not create instances of
+ `MGLTileSource` directly, and do not create your own subclasses of this class.
*/
MGL_EXPORT
@interface MGLTileSource : MGLSource
diff --git a/platform/darwin/src/MGLTileSource.mm b/platform/darwin/src/MGLTileSource.mm
index c37812ab8e..87ac5be9c2 100644
--- a/platform/darwin/src/MGLTileSource.mm
+++ b/platform/darwin/src/MGLTileSource.mm
@@ -2,6 +2,7 @@
#import "MGLAttributionInfo_Private.h"
#import "MGLGeometry_Private.h"
+#import "MGLRasterDEMSource.h"
#import "NSString+MGLAdditions.h"
#import "NSValue+MGLAdditions.h"
diff --git a/platform/darwin/src/MGLVectorStyleLayer.h b/platform/darwin/src/MGLVectorStyleLayer.h
index 177b1b70f0..d9431215a1 100644
--- a/platform/darwin/src/MGLVectorStyleLayer.h
+++ b/platform/darwin/src/MGLVectorStyleLayer.h
@@ -7,7 +7,7 @@ NS_ASSUME_NONNULL_BEGIN
/**
`MGLVectorStyleLayer` is an abstract superclass for style layers whose content
- is defined by an `MGLShapeSource` or `MGLVectorSource` object.
+ is defined by an `MGLShapeSource` or `MGLVectorTileSource` object.
Create instances of `MGLCircleStyleLayer`, `MGLFillStyleLayer`,
`MGLFillExtrusionStyleLayer`, `MGLHeatmapStyleLayer`, `MGLLineStyleLayer`, and
@@ -47,7 +47,7 @@ MGL_EXPORT
```swift
let layer = MGLLineStyleLayer(identifier: "contour", source: terrain)
layer.sourceLayerIdentifier = "contours"
- layer.predicate = NSPredicate(format: "(index == 5 || index == 10) && ele >= 1500.0")
+ layer.predicate = NSPredicate(format: "(index == 5 || index == 10) && CAST(ele, 'NSNumber') >= 1500.0")
mapView.style?.addLayer(layer)
```
*/
diff --git a/platform/darwin/src/MGLVectorSource.h b/platform/darwin/src/MGLVectorTileSource.h
index 968be3c0e0..790c9d4d42 100644
--- a/platform/darwin/src/MGLVectorSource.h
+++ b/platform/darwin/src/MGLVectorTileSource.h
@@ -5,29 +5,37 @@
NS_ASSUME_NONNULL_BEGIN
/**
- `MGLVectorSource` is a map content source that supplies tiled vector data in
- <a href="https://www.mapbox.com/vector-tiles/">Mapbox Vector Tile</a> format to
- be shown on the map. The location of and metadata about the tiles are defined
- either by an option dictionary or by an external file that conforms to the
+ `MGLVectorTileSource` is a map content source that supplies tiled vector data
+ in <a href="https://www.mapbox.com/vector-tiles/">Mapbox Vector Tile</a> format
+ to be shown on the map. The location of and metadata about the tiles are
+ defined either by an option dictionary or by an external file that conforms to
+ the
<a href="https://github.com/mapbox/tilejson-spec/">TileJSON specification</a>.
- A vector source is added to an `MGLStyle` object along with one or more
+ A vector tile source is added to an `MGLStyle` object along with one or more
`MGLVectorStyleLayer` objects. A vector style layer defines the appearance of
- any content supplied by the vector source.
+ any content supplied by the vector tile source.
+
+ `MGLVectorTileSource` is optimized for data sets that are too large to fit
+ completely in memory, such as vector tile sets or data sets managed in
+ <a href="https://www.mapbox.com/studio/">Mapbox Studio</a>. For
+ <a href="http://geojson.org/">GeoJSON</a> data, use the `MGLShapeSource`
+ class. For tiled data that changes dynamically, the `MGLComputedShapeSource`
+ class may be a suitable alternative.
Each
<a href="https://www.mapbox.com/mapbox-gl-style-spec/#sources-vector"><code>vector</code></a>
source defined by the style JSON file is represented at runtime by an
- `MGLVectorSource` object that you can use to initialize new style layers. You
- can also add and remove sources dynamically using methods such as
+ `MGLVectorTileSource` object that you can use to initialize new style layers.
+ You can also add and remove sources dynamically using methods such as
`-[MGLStyle addSource:]` and `-[MGLStyle sourceWithIdentifier:]`.
Within each vector tile, each geometric coordinate must lie between
−1&nbsp;×&nbsp;<var>extent</var> and
(<var>extent</var>&nbsp;×&nbsp;2)&nbsp;−&nbsp;1, inclusive. Any vector style
- layer initialized with a vector source must have a non-`nil` value in its
+ layer initialized with a vector tile source must have a non-`nil` value in its
`sourceLayerIdentifier` property.
- Commonly used vector sources include
+ Commonly used vector tile sources include
<a href="https://www.mapbox.com/vector-tiles/mapbox-streets/">Mapbox Streets</a>,
<a href="https://www.mapbox.com/vector-tiles/mapbox-terrain/">Mapbox Terrain</a>,
and
@@ -36,23 +44,24 @@ NS_ASSUME_NONNULL_BEGIN
### Example
```swift
- let source = MGLVectorSource(identifier: "pois", tileURLTemplates: ["https://example.com/vector-tiles/{z}/{x}/{y}.mvt"], options: [
+ let source = MGLVectorTileSource(identifier: "pois", tileURLTemplates: ["https://example.com/vector-tiles/{z}/{x}/{y}.mvt"], options: [
.minimumZoomLevel: 9,
.maximumZoomLevel: 16,
.attributionInfos: [
- MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com"))
+ MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "https://mapbox.com"))
]
])
mapView.style?.addSource(source)
```
*/
MGL_EXPORT
-@interface MGLVectorSource : MGLTileSource
+@interface MGLVectorTileSource : MGLTileSource
#pragma mark Initializing a Source
/**
- Returns a vector source initialized with an identifier and configuration URL.
+ Returns a vector tile source initialized with an identifier and configuration
+ URL.
After initializing and configuring the source, add it to a map view’s style
using the `-[MGLStyle addSource:]` method.
@@ -66,12 +75,12 @@ MGL_EXPORT
which it is added.
@param configurationURL A URL to a TileJSON configuration file describing the
source’s contents and other metadata.
- @return An initialized vector source.
+ @return An initialized vector tile source.
*/
- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL NS_DESIGNATED_INITIALIZER;
/**
- Returns a vector source initialized an identifier, tile URL templates, and
+ Returns a vector tile source initialized an identifier, tile URL templates, and
options.
Tile URL templates are strings that specify the URLs of the vector tiles to
diff --git a/platform/darwin/src/MGLVectorSource.mm b/platform/darwin/src/MGLVectorTileSource.mm
index 90ffe6f98b..c1f7267e4a 100644
--- a/platform/darwin/src/MGLVectorSource.mm
+++ b/platform/darwin/src/MGLVectorTileSource.mm
@@ -1,4 +1,4 @@
-#import "MGLVectorSource_Private.h"
+#import "MGLVectorTileSource_Private.h"
#import "MGLFeature_Private.h"
#import "MGLSource_Private.h"
@@ -13,13 +13,13 @@
#include <mbgl/style/sources/vector_source.hpp>
#include <mbgl/renderer/renderer.hpp>
-@interface MGLVectorSource ()
+@interface MGLVectorTileSource ()
@property (nonatomic, readonly) mbgl::style::VectorSource *rawSource;
@end
-@implementation MGLVectorSource
+@implementation MGLVectorTileSource
- (instancetype)initWithIdentifier:(NSString *)identifier configurationURL:(NSURL *)configurationURL {
auto source = std::make_unique<mbgl::style::VectorSource>(identifier.UTF8String,
@@ -73,30 +73,57 @@
@end
-@implementation MGLVectorSource (Private)
+@implementation MGLVectorTileSource (Private)
+
+/**
+ An array of locale codes with dedicated name fields in the Mapbox Streets
+ source.
+
+ https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview
+ */
+static NSArray * const MGLMapboxStreetsLanguages = @[
+ @"ar", @"de", @"en", @"es", @"fr", @"pt", @"ru", @"zh", @"zh-Hans",
+];
+
+/**
+ Like `MGLMapboxStreetsLanguages`, but deanglicized for use with
+ `+[NSBundle preferredLocalizationsFromArray:forPreferences:]`.
+ */
+static NSArray * const MGLMapboxStreetsAlternativeLanguages = @[
+ @"mul", @"ar", @"de", @"es", @"fr", @"pt", @"ru", @"zh", @"zh-Hans",
+];
+ (NS_SET_OF(NSString *) *)mapboxStreetsLanguages {
- // https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview
static dispatch_once_t onceToken;
static NS_SET_OF(NSString *) *mapboxStreetsLanguages;
dispatch_once(&onceToken, ^{
- // https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview
- mapboxStreetsLanguages = [NSSet setWithObjects:@"ar", @"de", @"en", @"es", @"fr", @"pt", @"ru", @"zh", @"zh-Hans", nil];
+ mapboxStreetsLanguages = [NSSet setWithArray:MGLMapboxStreetsLanguages];
});
return mapboxStreetsLanguages;
}
+ (NSString *)preferredMapboxStreetsLanguage {
- NSArray<NSString *> *supportedLanguages = [MGLVectorSource mapboxStreetsLanguages].allObjects;
- NSArray<NSString *> *preferredLanguages = [NSBundle preferredLocalizationsFromArray:supportedLanguages
- forPreferences:[NSLocale preferredLanguages]];
+ return [self preferredMapboxStreetsLanguageForPreferences:[NSLocale preferredLanguages]];
+}
+
++ (NSString *)preferredMapboxStreetsLanguageForPreferences:(NSArray<NSString *> *)preferencesArray {
+ BOOL acceptsEnglish = [preferencesArray filteredArrayUsingPredicate:
+ [NSPredicate predicateWithBlock:^BOOL(NSString * _Nullable language, NSDictionary<NSString *,id> * _Nullable bindings) {
+ return [[NSLocale localeWithLocaleIdentifier:language].languageCode isEqualToString:@"en"];
+ }]].count;
+
+ NSArray<NSString *> *preferredLanguages = [NSBundle preferredLocalizationsFromArray:MGLMapboxStreetsAlternativeLanguages
+ forPreferences:preferencesArray];
NSString *mostSpecificLanguage;
for (NSString *language in preferredLanguages) {
if (language.length > mostSpecificLanguage.length) {
mostSpecificLanguage = language;
}
}
- return mostSpecificLanguage ?: @"en";
+ if ([mostSpecificLanguage isEqualToString:@"mul"]) {
+ return acceptsEnglish ? @"en" : nil;
+ }
+ return mostSpecificLanguage;
}
- (BOOL)isMapboxStreets {
@@ -116,7 +143,7 @@
// Replace {name} and {name_*} with the matching localized name tag.
NSString *localizedKey = preferredLanguage ? [NSString stringWithFormat:@"name_%@", preferredLanguage] : @"name";
NSMutableDictionary *localizedKeysByKey = [NSMutableDictionary dictionaryWithObject:localizedKey forKey:@"name"];
- for (NSString *languageCode in [MGLVectorSource mapboxStreetsLanguages]) {
+ for (NSString *languageCode in [MGLVectorTileSource mapboxStreetsLanguages]) {
NSString *key = [NSString stringWithFormat:@"name_%@", languageCode];
localizedKeysByKey[key] = localizedKey;
}
diff --git a/platform/darwin/src/MGLVectorSource_Private.h b/platform/darwin/src/MGLVectorTileSource_Private.h
index 7d19e03a99..77521869f1 100644
--- a/platform/darwin/src/MGLVectorSource_Private.h
+++ b/platform/darwin/src/MGLVectorTileSource_Private.h
@@ -1,14 +1,15 @@
-#import "MGLVectorSource.h"
+#import "MGLVectorTileSource.h"
NS_ASSUME_NONNULL_BEGIN
-@interface MGLVectorSource (Private)
+@interface MGLVectorTileSource (Private)
@property (nonatomic, readonly, getter=isMapboxStreets) BOOL mapboxStreets;
+ (NS_SET_OF(NSString *) *)mapboxStreetsLanguages;
-+ (NSString *)preferredMapboxStreetsLanguage;
++ (nullable NSString *)preferredMapboxStreetsLanguage;
++ (nullable NSString *)preferredMapboxStreetsLanguageForPreferences:(NSArray<NSString *> *)preferencesArray;
- (NS_DICTIONARY_OF(NSString *, NSString *) *)localizedKeysByKeyForPreferredLanguage:(nullable NSString *)preferredLanguage;
diff --git a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm
index 5b54d66aeb..380215ff32 100644
--- a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm
+++ b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm
@@ -1,231 +1,12 @@
#import "NSComparisonPredicate+MGLAdditions.h"
+#import "MGLStyleValue_Private.h"
+
#import "NSPredicate+MGLAdditions.h"
#import "NSExpression+MGLPrivateAdditions.h"
@implementation NSComparisonPredicate (MGLAdditions)
-- (mbgl::style::Filter)mgl_filter {
- NSExpression *leftExpression = self.leftExpression;
- NSExpression *rightExpression = self.rightExpression;
- NSExpressionType leftType = leftExpression.expressionType;
- NSExpressionType rightType = rightExpression.expressionType;
- BOOL isReversed = ((leftType == NSConstantValueExpressionType || leftType == NSAggregateExpressionType)
- && rightType == NSKeyPathExpressionType);
- switch (self.predicateOperatorType) {
- case NSEqualToPredicateOperatorType: {
- mbgl::style::EqualsFilter eqFilter;
- eqFilter.key = self.mgl_keyPath.UTF8String;
- eqFilter.value = self.mgl_constantValue;
-
- // Convert $type == to TypeEqualsFilter.
- if (eqFilter.key == "$type") {
- mbgl::style::TypeEqualsFilter typeEqFilter;
- typeEqFilter.value = self.mgl_featureType;
- return typeEqFilter;
- }
-
- // Convert $id == to IdentifierEqualsFilter.
- if (eqFilter.key == "$id") {
- // Convert $id == nil to NotHasIdentifierFilter.
- if (eqFilter.value.is<mbgl::NullValue>()) {
- return mbgl::style::NotHasIdentifierFilter();
- }
-
- mbgl::style::IdentifierEqualsFilter idEqFilter;
- idEqFilter.value = self.mgl_featureIdentifier;
- return idEqFilter;
- }
-
- // Convert == nil to NotHasFilter.
- if (eqFilter.value.is<mbgl::NullValue>()) {
- mbgl::style::NotHasFilter notHasFilter;
- notHasFilter.key = eqFilter.key;
- return notHasFilter;
- }
-
- return eqFilter;
- }
- case NSNotEqualToPredicateOperatorType: {
- mbgl::style::NotEqualsFilter neFilter;
- neFilter.key = self.mgl_keyPath.UTF8String;
- neFilter.value = self.mgl_constantValue;
-
- // Convert $type != to TypeNotEqualsFilter.
- if (neFilter.key == "$type") {
- mbgl::style::TypeNotEqualsFilter typeNeFilter;
- typeNeFilter.value = self.mgl_featureType;
- return typeNeFilter;
- }
-
- // Convert $id != to IdentifierNotEqualsFilter.
- if (neFilter.key == "$id") {
- // Convert $id != nil to HasIdentifierFilter.
- if (neFilter.value.is<mbgl::NullValue>()) {
- return mbgl::style::HasIdentifierFilter();
- }
-
- mbgl::style::IdentifierNotEqualsFilter idNeFilter;
- idNeFilter.value = self.mgl_featureIdentifier;
- return idNeFilter;
- }
-
- // Convert != nil to HasFilter.
- if (neFilter.value.is<mbgl::NullValue>()) {
- mbgl::style::HasFilter hasFilter;
- hasFilter.key = neFilter.key;
- return hasFilter;
- }
-
- return neFilter;
- }
- case NSGreaterThanPredicateOperatorType: {
- if (isReversed) {
- mbgl::style::LessThanFilter ltFilter;
- ltFilter.key = self.mgl_keyPath.UTF8String;
- ltFilter.value = self.mgl_constantValue;
- return ltFilter;
- } else {
- mbgl::style::GreaterThanFilter gtFilter;
- gtFilter.key = self.mgl_keyPath.UTF8String;
- gtFilter.value = self.mgl_constantValue;
- return gtFilter;
- }
- }
- case NSGreaterThanOrEqualToPredicateOperatorType: {
- if (isReversed) {
- mbgl::style::LessThanEqualsFilter lteFilter;
- lteFilter.key = self.mgl_keyPath.UTF8String;
- lteFilter.value = self.mgl_constantValue;
- return lteFilter;
- } else {
- mbgl::style::GreaterThanEqualsFilter gteFilter;
- gteFilter.key = self.mgl_keyPath.UTF8String;
- gteFilter.value = self.mgl_constantValue;
- return gteFilter;
- }
- }
- case NSLessThanPredicateOperatorType: {
- if (isReversed) {
- mbgl::style::GreaterThanFilter gtFilter;
- gtFilter.key = self.mgl_keyPath.UTF8String;
- gtFilter.value = self.mgl_constantValue;
- return gtFilter;
- } else {
- mbgl::style::LessThanFilter ltFilter;
- ltFilter.key = self.mgl_keyPath.UTF8String;
- ltFilter.value = self.mgl_constantValue;
- return ltFilter;
- }
- }
- case NSLessThanOrEqualToPredicateOperatorType: {
- if (isReversed) {
- mbgl::style::GreaterThanEqualsFilter gteFilter;
- gteFilter.key = self.mgl_keyPath.UTF8String;
- gteFilter.value = self.mgl_constantValue;
- return gteFilter;
- } else {
- mbgl::style::LessThanEqualsFilter lteFilter;
- lteFilter.key = self.mgl_keyPath.UTF8String;
- lteFilter.value = self.mgl_constantValue;
- return lteFilter;
- }
- }
- case NSInPredicateOperatorType: {
- if (isReversed) {
- if (leftType == NSConstantValueExpressionType && [leftExpression.constantValue isKindOfClass:[NSString class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"CONTAINS not supported for string comparison."];
- }
- [NSException raise:NSInvalidArgumentException
- format:@"Predicate cannot compare values IN attribute."];
- }
-
- // Convert $type IN to TypeInFilter.
- if ([leftExpression.keyPath isEqualToString:@"$type"]) {
- mbgl::style::TypeInFilter typeInFilter;
- typeInFilter.values = rightExpression.mgl_aggregateFeatureType;
- return typeInFilter;
- }
-
- // Convert $id IN to IdentifierInFilter.
- if ([leftExpression.keyPath isEqualToString:@"$id"]) {
- mbgl::style::IdentifierInFilter idInFilter;
- idInFilter.values = rightExpression.mgl_aggregateFeatureIdentifier;
- return idInFilter;
- }
-
- mbgl::style::InFilter inFilter;
- inFilter.key = leftExpression.keyPath.UTF8String;
- inFilter.values = rightExpression.mgl_aggregateMBGLValue;
- return inFilter;
- }
- case NSContainsPredicateOperatorType: {
- if (!isReversed) {
- if (rightType == NSConstantValueExpressionType && [rightExpression.constantValue isKindOfClass:[NSString class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"IN not supported for string comparison."];
- }
- [NSException raise:NSInvalidArgumentException
- format:@"Predicate cannot compare attribute CONTAINS values."];
- }
-
- // Convert CONTAINS $type to TypeInFilter.
- if ([rightExpression.keyPath isEqualToString:@"$type"]) {
- mbgl::style::TypeInFilter typeInFilter;
- typeInFilter.values = leftExpression.mgl_aggregateFeatureType;
- return typeInFilter;
- }
-
- // Convert CONTAINS $id to IdentifierInFilter.
- if ([rightExpression.keyPath isEqualToString:@"$id"]) {
- mbgl::style::IdentifierInFilter idInFilter;
- idInFilter.values = leftExpression.mgl_aggregateFeatureIdentifier;
- return idInFilter;
- }
-
- mbgl::style::InFilter inFilter;
- inFilter.key = rightExpression.keyPath.UTF8String;
- inFilter.values = leftExpression.mgl_aggregateMBGLValue;
- return inFilter;
- }
- case NSBetweenPredicateOperatorType: {
- if (isReversed) {
- [NSException raise:NSInvalidArgumentException
- format:@"Predicate cannot compare bounds BETWEEN attribute."];
- }
- if (![rightExpression.constantValue isKindOfClass:[NSArray class]]) {
- [NSException raise:NSInvalidArgumentException
- format:@"Right side of BETWEEN predicate must be an array."]; // not NSSet
- }
- auto values = rightExpression.mgl_aggregateMBGLValue;
- if (values.size() != 2) {
- [NSException raise:NSInvalidArgumentException
- format:@"Right side of BETWEEN predicate must have two items."];
- }
- mbgl::style::AllFilter allFilter;
- mbgl::style::GreaterThanEqualsFilter gteFilter;
- gteFilter.key = leftExpression.keyPath.UTF8String;
- gteFilter.value = values[0];
- allFilter.filters.push_back(gteFilter);
- mbgl::style::LessThanEqualsFilter lteFilter;
- lteFilter.key = leftExpression.keyPath.UTF8String;
- lteFilter.value = values[1];
- allFilter.filters.push_back(lteFilter);
- return allFilter;
- }
- case NSMatchesPredicateOperatorType:
- case NSLikePredicateOperatorType:
- case NSBeginsWithPredicateOperatorType:
- case NSEndsWithPredicateOperatorType:
- case NSCustomSelectorPredicateOperatorType:
- [NSException raise:NSInvalidArgumentException
- format:@"NSPredicateOperatorType:%lu is not supported.", (unsigned long)self.predicateOperatorType];
- }
-
- return {};
-}
-
- (NSString *)mgl_keyPath {
NSExpression *leftExpression = self.leftExpression;
NSExpression *rightExpression = self.rightExpression;
@@ -318,14 +99,45 @@
case NSNotEqualToPredicateOperatorType:
op = @"!=";
break;
+ case NSBetweenPredicateOperatorType: {
+ op = @"all";
+ NSArray *limits = self.rightExpression.constantValue;
+ NSPredicate *leftHandPredicate = [NSComparisonPredicate predicateWithLeftExpression:limits[0]
+ rightExpression:self.leftExpression
+ modifier:NSDirectPredicateModifier
+ type:NSLessThanOrEqualToPredicateOperatorType
+ options:0];
+ NSPredicate *rightHandPredicate = [NSComparisonPredicate predicateWithLeftExpression:self.leftExpression
+ rightExpression:limits[1]
+ modifier:NSDirectPredicateModifier
+ type:NSLessThanOrEqualToPredicateOperatorType
+ options:0];
+ return @[op, leftHandPredicate.mgl_jsonExpressionObject, rightHandPredicate.mgl_jsonExpressionObject];
+ }
+ case NSInPredicateOperatorType: {
+ NSMutableArray *elements = [NSMutableArray arrayWithObjects:@"match", self.leftExpression.mgl_jsonExpressionObject, nil];
+ NSArray *optionsExpressions = self.rightExpression.constantValue;
+ for (id object in optionsExpressions) {
+ id option = ((NSExpression *)object).mgl_jsonExpressionObject;
+ [elements addObject:option];
+ [elements addObject:@YES];
+ }
+ [elements addObject:@NO];
+ return elements;
+ }
+ case NSContainsPredicateOperatorType: {
+ NSPredicate *inPredicate = [NSComparisonPredicate predicateWithLeftExpression:self.rightExpression
+ rightExpression:self.leftExpression
+ modifier:self.comparisonPredicateModifier
+ type:NSInPredicateOperatorType
+ options:self.options];
+ return inPredicate.mgl_jsonExpressionObject;
+ }
case NSMatchesPredicateOperatorType:
case NSLikePredicateOperatorType:
case NSBeginsWithPredicateOperatorType:
case NSEndsWithPredicateOperatorType:
- case NSInPredicateOperatorType:
case NSCustomSelectorPredicateOperatorType:
- case NSContainsPredicateOperatorType:
- case NSBetweenPredicateOperatorType:
[NSException raise:NSInvalidArgumentException
format:@"NSPredicateOperatorType:%lu is not supported.", (unsigned long)self.predicateOperatorType];
}
diff --git a/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm b/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm
index 19568b8033..5a98b763ea 100644
--- a/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm
+++ b/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm
@@ -1,8 +1,12 @@
#import "NSCompoundPredicate+MGLAdditions.h"
+#import "MGLStyleValue_Private.h"
+
#import "NSPredicate+MGLAdditions.h"
#import "NSExpression+MGLPrivateAdditions.h"
+#include <mbgl/style/conversion/property_value.hpp>
+
@implementation NSCompoundPredicate (MGLAdditions)
- (std::vector<mbgl::style::Filter>)mgl_subfilters
@@ -14,62 +18,6 @@
return filters;
}
-- (mbgl::style::Filter)mgl_filter
-{
- switch (self.compoundPredicateType) {
- case NSNotPredicateType: {
- NSAssert(self.subpredicates.count <= 1, @"NOT predicate cannot have multiple subpredicates.");
- NSPredicate *subpredicate = self.subpredicates.firstObject;
- mbgl::style::Filter subfilter = subpredicate.mgl_filter;
-
- // Convert NOT(!= nil) to NotHasFilter.
- if (subfilter.is<mbgl::style::HasFilter>()) {
- auto hasFilter = subfilter.get<mbgl::style::HasFilter>();
- return mbgl::style::NotHasFilter { .key = hasFilter.key };
- }
-
- // Convert NOT(== nil) to HasFilter.
- if (subfilter.is<mbgl::style::NotHasFilter>()) {
- auto hasFilter = subfilter.get<mbgl::style::NotHasFilter>();
- return mbgl::style::HasFilter { .key = hasFilter.key };
- }
-
- // Convert NOT(IN) or NOT(CONTAINS) to NotInFilter.
- if (subfilter.is<mbgl::style::InFilter>()) {
- auto inFilter = subfilter.get<mbgl::style::InFilter>();
- mbgl::style::NotInFilter notInFilter;
- notInFilter.key = inFilter.key;
- notInFilter.values = inFilter.values;
- return notInFilter;
- }
-
- // Convert NOT(), NOT(AND), NOT(NOT), NOT(==), etc. into NoneFilter.
- mbgl::style::NoneFilter noneFilter;
- if (subfilter.is<mbgl::style::AnyFilter>()) {
- // Flatten NOT(OR).
- noneFilter.filters = subfilter.get<mbgl::style::AnyFilter>().filters;
- } else if (subpredicate) {
- noneFilter.filters = { subfilter };
- }
- return noneFilter;
- }
- case NSAndPredicateType: {
- mbgl::style::AllFilter filter;
- filter.filters = self.mgl_subfilters;
- return filter;
- }
- case NSOrPredicateType: {
- mbgl::style::AnyFilter filter;
- filter.filters = self.mgl_subfilters;
- return filter;
- }
- }
-
- [NSException raise:@"Compound predicate type not handled"
- format:@""];
- return {};
-}
-
@end
@implementation NSCompoundPredicate (MGLExpressionAdditions)
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.h b/platform/darwin/src/NSExpression+MGLAdditions.h
index b4d36bc1b1..cfdf27aade 100644
--- a/platform/darwin/src/NSExpression+MGLAdditions.h
+++ b/platform/darwin/src/NSExpression+MGLAdditions.h
@@ -9,15 +9,150 @@
NS_ASSUME_NONNULL_BEGIN
+typedef NSString *MGLExpressionInterpolationMode NS_TYPED_ENUM;
+
+/**
+ An `NSString` identifying the `linear` interpolation type in an `NSExpression`.
+
+ This attribute corresponds to the `linear` value in the
+ <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-interpolate"><code>interpolate</code></a>
+ expression operator in the Mapbox Style Specification.
+ */
+extern MGL_EXPORT const MGLExpressionInterpolationMode MGLExpressionInterpolationModeLinear;
+
+/**
+ An `NSString` identifying the `expotential` interpolation type in an `NSExpression`.
+
+ This attribute corresponds to the `exponential` value in the
+ <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-interpolate"><code>interpolate</code></a>
+ expression operator in the Mapbox Style Specification.
+ */
+extern MGL_EXPORT const MGLExpressionInterpolationMode MGLExpressionInterpolationModeExponential;
+
+/**
+ An `NSString` identifying the `cubic-bezier` interpolation type in an `NSExpression`.
+
+ This attribute corresponds to the `cubic-bezier` value in the
+ <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-interpolate"><code>interpolate</code></a>
+ expression operator in the Mapbox Style Specification.
+ */
+extern MGL_EXPORT const MGLExpressionInterpolationMode MGLExpressionInterpolationModeCubicBezier;
+
+/**
+ Methods for creating expressions that use Mapbox-specific functionality and for
+ converting to and from the JSON format defined in the
+ <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions">Mapbox Style Specification</a>.
+ */
@interface NSExpression (MGLAdditions)
+#pragma mark Creating Variable Expressions
+
+/**
+ `NSExpression` variable that corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-zoom"><code>zoom</code></a>
+ expression operator in the Mapbox Style Specification.
+ */
+@property (class, nonatomic, readonly) NSExpression *zoomLevelVariableExpression;
+
+/**
+ `NSExpression` variable that corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-heatmap-density"><code>heatmap-density</code></a>
+ expression operator in the Mapbox Style Specification.
+ */
+@property (class, nonatomic, readonly) NSExpression *heatmapDensityVariableExpression;
+
+/**
+ `NSExpression` variable that corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#eexpressions-geometry-type"><code>geometry-type</code></a>
+ expression operator in the Mapbox Style Specification.
+ */
+@property (class, nonatomic, readonly) NSExpression *geometryTypeVariableExpression;
+
+/**
+ `NSExpression` variable that corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-id"><code>id</code></a>
+ expression operator in the Mapbox Style Specification.
+ */
+@property (class, nonatomic, readonly) NSExpression *featureIdentifierVariableExpression;
+
+/**
+ `NSExpression` variable that corresponds to the
+ <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-properties"><code>properties</code></a>
+ expression operator in the Mapbox Style Specification.
+ */
+@property (class, nonatomic, readonly) NSExpression *featureAttributesVariableExpression;
+
+@property (class, nonatomic, readonly) NSExpression *featurePropertiesVariableExpression __attribute__((deprecated("Use -featureAttributesVariableExpression.")));
+
+#pragma mark Creating Conditional Expressions
+
+/**
+ Returns a conditional function expression specifying the string predicate, and
+ expressions for each condition.
+
+ @param conditionPredicate The predicate to get evaluated.
+ @param trueExpression The expression for conditions equal to true.
+ @param falseExpression The expression for conditions equal to false.
+ */
++ (instancetype)mgl_expressionForConditional:(nonnull NSPredicate *)conditionPredicate trueExpression:(nonnull NSExpression *)trueExpression falseExpresssion:(nonnull NSExpression *)falseExpression NS_SWIFT_NAME(init(forMGLConditional:trueExpression:falseExpression:));
+
+#pragma mark Creating Ramp, Scale, and Curve Expressions
+
+/**
+ Returns a step function expression specifying the stepping, from expression
+ and stops.
+
+ @param steppingExpression The stepping expression.
+ @param minimumExpression The expression which could be a constant or function expression.
+ @param stops The stops must be an `NSDictionary` constant `NSExpression`.
+ */
++ (instancetype)mgl_expressionForSteppingExpression:(nonnull NSExpression*)steppingExpression fromExpression:(nonnull NSExpression *)minimumExpression stops:(nonnull NSExpression*)stops NS_SWIFT_NAME(init(forMGLStepping:from:stops:));
+
+/**
+ Returns an interpolated function expression specifying the function operator, curve type,
+ parameters and steps.
+
+ @param inputExpression The interpolating expression input.
+ @param curveType The curve type could be `MGLExpressionInterpolationModeLinear`,
+ `MGLExpressionInterpolationModeExponential` and
+ `MGLExpressionInterpolationModeCubicBezier`.
+ @param parameters The parameters expression.
+ @param stops The stops expression.
+ */
++ (instancetype)mgl_expressionForInterpolatingExpression:(nonnull NSExpression*)inputExpression withCurveType:(nonnull MGLExpressionInterpolationMode)curveType parameters:(nullable NSExpression *)parameters stops:(nonnull NSExpression*)stops NS_SWIFT_NAME(init(forMGLInterpolating:curveType:parameters:stops:));
+
+/**
+ Returns a match function expression specifying the input, matching values,
+ and default value.
+
+ @param inputExpression The matching expression.
+ @param matchedExpressions The matched values expression dictionary must be condition : value.
+ @param defaultExpression The defaultValue expression to be used in case there is no match.
+ */
++ (instancetype)mgl_expressionForMatchingExpression:(nonnull NSExpression *)inputExpression inDictionary:(nonnull NSDictionary<NSExpression *, NSExpression *> *)matchedExpressions defaultExpression:(nonnull NSExpression *)defaultExpression NS_SWIFT_NAME(init(forMGLMatchingKey:in:default:));
+
+#pragma mark Concatenating String Expressions
+
+/**
+ Returns a constant expression appending the passed expression.
+
+ @note Both the receiver and the given expression must be an `NSString` constant
+ expression type; otherwise, an exception is rised.
+
+ @param expression The expression to append to the receiver.
+ */
+- (instancetype)mgl_expressionByAppendingExpression:(nonnull NSExpression *)expression NS_SWIFT_NAME(mgl_appending(_:));
+
+#pragma mark Converting JSON Expressions
+
/**
Returns an expression equivalent to the given Foundation object deserialized
from JSON data.
The Foundation object is interpreted according to the
[Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions).
- See the “[Predicates and Expressions](../predicates-and-expressions.html)”
+ See the
+ “[Information for Style Authors](../for-style-authors.html#setting-attribute-values)”
guide for a correspondence of operators and types between the style
specification and the `NSExpression` representation used by this SDK.
@@ -26,14 +161,15 @@ NS_ASSUME_NONNULL_BEGIN
@return An initialized expression equivalent to `object`, suitable for use as
the value of a style layer attribute.
*/
-+ (instancetype)mgl_expressionWithJSONObject:(id)object;
++ (instancetype)expressionWithMGLJSONObject:(id)object NS_SWIFT_NAME(init(mglJSONObject:));
/**
An equivalent Foundation object that can be serialized as JSON.
The Foundation object conforms to the
[Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions).
- See the “[Predicates and Expressions](../predicates-and-expressions.html)”
+ See the
+ “[Information for Style Authors](../for-style-authors.html#setting-attribute-values)”
guide for a correspondence of operators and types between the style
specification and the `NSExpression` representation used by this SDK.
@@ -42,6 +178,24 @@ NS_ASSUME_NONNULL_BEGIN
*/
@property (nonatomic, readonly) id mgl_jsonExpressionObject;
+#pragma mark Localizing the Expression
+
+/**
+ Returns a copy of the receiver localized into the given locale.
+
+ This method assumes the receiver refers to the feature attributes that are
+ available in vector tiles supplied by the
+ <a href="https://www.mapbox.com/vector-tiles/mapbox-streets-v7/#overview">Mapbox Streets source</a>.
+ On iOS, the user can set the system’s preferred language in Settings, General
+ Settings, Language & Region. On macOS, the user can set the system’s preferred
+ language in the Language & Region pane of System Preferences.
+
+ @param locale The locale into which labels should be localized. To use the
+ system’s preferred language, if supported, specify `nil`. To use the local
+ language, specify a locale with the identifier `mul`.
+ */
+- (NSExpression *)mgl_expressionLocalizedIntoLocale:(nullable NSLocale *)locale;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm
index 5ad565c398..c82a7dc008 100644
--- a/platform/darwin/src/NSExpression+MGLAdditions.mm
+++ b/platform/darwin/src/NSExpression+MGLAdditions.mm
@@ -10,9 +10,239 @@
#endif
#import "NSPredicate+MGLAdditions.h"
#import "NSValue+MGLStyleAttributeAdditions.h"
+#import "MGLVectorTileSource_Private.h"
+
+#import <objc/runtime.h>
#import <mbgl/style/expression/expression.hpp>
+const MGLExpressionInterpolationMode MGLExpressionInterpolationModeLinear = @"linear";
+const MGLExpressionInterpolationMode MGLExpressionInterpolationModeExponential = @"exponential";
+const MGLExpressionInterpolationMode MGLExpressionInterpolationModeCubicBezier = @"cubic-bezier";
+
+@interface MGLAftermarketExpressionInstaller: NSObject
+@end
+
+@implementation MGLAftermarketExpressionInstaller
+
++ (void)load {
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+ [self installFunctions];
+ });
+}
+
+/**
+ Adds to NSExpression’s built-in repertoire of functions.
+ */
++ (void)installFunctions {
+ Class MGLAftermarketExpressionInstaller = [self class];
+
+ // NSExpression’s built-in functions are backed by class methods on a
+ // private class, so use a function expression to get at the class.
+ // http://funwithobjc.tumblr.com/post/2922267976/using-custom-functions-with-nsexpression
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"sum({})"];
+ NSString *className = NSStringFromClass([functionExpression.operand.constantValue class]);
+
+ // Effectively categorize the class with some extra class methods.
+ Class NSPredicateUtilities = objc_getMetaClass(className.UTF8String);
+#pragma clang push
+#pragma clang diagnostic ignored "-Wundeclared-selector"
+ #define INSTALL_METHOD(sel) \
+ { \
+ Method method = class_getInstanceMethod(MGLAftermarketExpressionInstaller, @selector(sel)); \
+ class_addMethod(NSPredicateUtilities, @selector(sel), method_getImplementation(method), method_getTypeEncoding(method)); \
+ }
+ #define INSTALL_CONTROL_STRUCTURE(sel) \
+ { \
+ Method method = class_getInstanceMethod(MGLAftermarketExpressionInstaller, @selector(sel:)); \
+ class_addMethod(NSPredicateUtilities, @selector(sel), method_getImplementation(method), method_getTypeEncoding(method)); \
+ class_addMethod(NSPredicateUtilities, @selector(sel:), method_getImplementation(method), method_getTypeEncoding(method)); \
+ }
+
+ // Install method-like functions, taking the number of arguments implied by
+ // the selector name.
+ INSTALL_METHOD(mgl_join:);
+ INSTALL_METHOD(mgl_round:);
+ INSTALL_METHOD(mgl_interpolate:withCurveType:parameters:stops:);
+ INSTALL_METHOD(mgl_step:from:stops:);
+ INSTALL_METHOD(mgl_coalesce:);
+ INSTALL_METHOD(mgl_does:have:);
+ INSTALL_METHOD(mgl_acos:);
+ INSTALL_METHOD(mgl_cos:);
+ INSTALL_METHOD(mgl_asin:);
+ INSTALL_METHOD(mgl_sin:);
+ INSTALL_METHOD(mgl_atan:);
+ INSTALL_METHOD(mgl_tan:);
+ INSTALL_METHOD(mgl_log2:);
+
+ // Install functions that resemble control structures, taking arbitrary
+ // numbers of arguments. Vararg aftermarket functions need to be declared
+ // with an explicit and implicit first argument.
+ INSTALL_CONTROL_STRUCTURE(MGL_LET);
+ INSTALL_CONTROL_STRUCTURE(MGL_MATCH);
+ INSTALL_CONTROL_STRUCTURE(MGL_IF);
+ INSTALL_CONTROL_STRUCTURE(MGL_FUNCTION);
+
+ #undef INSTALL_AFTERMARKET_FN
+#pragma clang pop
+}
+
+/**
+ Joins the given components into a single string by concatenating each component
+ in order.
+ */
+- (NSString *)mgl_join:(NSArray<NSString *> *)components {
+ return [components componentsJoinedByString:@""];
+}
+
+/**
+ Rounds the given number to the nearest integer. If the number is halfway
+ between two integers, this method rounds it away from zero.
+ */
+- (NSNumber *)mgl_round:(NSNumber *)number {
+ return @(round(number.doubleValue));
+}
+
+/**
+ Computes the principal value of the inverse cosine.
+ */
+- (NSNumber *)mgl_acos:(NSNumber *)number {
+ return @(acos(number.doubleValue));
+}
+
+/**
+ Computes the principal value of the cosine.
+ */
+- (NSNumber *)mgl_cos:(NSNumber *)number {
+ return @(cos(number.doubleValue));
+}
+
+/**
+ Computes the principal value of the inverse sine.
+ */
+- (NSNumber *)mgl_asin:(NSNumber *)number {
+ return @(asin(number.doubleValue));
+}
+
+/**
+ Computes the principal value of the sine.
+ */
+- (NSNumber *)mgl_sin:(NSNumber *)number {
+ return @(sin(number.doubleValue));
+}
+
+/**
+ Computes the principal value of the inverse tangent.
+ */
+- (NSNumber *)mgl_atan:(NSNumber *)number {
+ return @(atan(number.doubleValue));
+}
+
+/**
+ Computes the principal value of the tangent.
+ */
+- (NSNumber *)mgl_tan:(NSNumber *)number {
+ return @(tan(number.doubleValue));
+}
+
+/**
+ Computes the logarithm base two of the value.
+ */
+- (NSNumber *)mgl_log2:(NSNumber *)number {
+ return @(log2(number.doubleValue));
+}
+
+/**
+ A placeholder for a method that evaluates an interpolation expression.
+ */
+- (id)mgl_interpolate:(id)inputExpression withCurveType:(NSString *)curveType parameters:(NSDictionary *)params stops:(NSDictionary *)stops {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Interpolation expressions lack underlying Objective-C implementations."];
+ return nil;
+}
+
+/**
+ A placeholder for a method that evaluates a step expression.
+ */
+- (id)mgl_step:(id)inputExpression from:(id)minimumExpression stops:(NSDictionary *)stops {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Step expressions lack underlying Objective-C implementations."];
+ return nil;
+}
+
+/**
+ A placeholder for a method that evaluates a coalesce expression.
+ */
+- (id)mgl_coalesce:(NSArray<NSExpression *> *)elements {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Coalesce expressions lack underlying Objective-C implementations."];
+ return nil;
+}
+
+/**
+ Returns a Boolean value indicating whether the object has a value for the given
+ key.
+ */
+- (BOOL)mgl_does:(id)object have:(NSString *)key {
+ return [object valueForKey:key] != nil;
+}
+
+/**
+ A placeholder for a method that evaluates an expression based on an arbitrary
+ number of variable names and assigned expressions.
+ */
+- (id)MGL_LET:(NSString *)firstVariableName, ... {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Assignment expressions lack underlying Objective-C implementations."];
+ return nil;
+}
+
+/**
+ A placeholder for a method that evaluates an expression and returns the matching element.
+ */
+- (id)MGL_MATCH:(id)firstCondition, ... {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Assignment expressions lack underlying Objective-C implementations."];
+ return nil;
+}
+
+/**
+ A placeholder for a method that evaluates an expression and returns the matching element.
+ */
+- (id)MGL_IF:(id)firstCondition, ... {
+ va_list argumentList;
+ va_start(argumentList, firstCondition);
+
+ for (id eachExpression = firstCondition; eachExpression; eachExpression = va_arg(argumentList, id)) {
+ if ([eachExpression isKindOfClass:[NSComparisonPredicate class]]) {
+ id valueExpression = va_arg(argumentList, id);
+ if ([eachExpression evaluateWithObject:nil]) {
+ return valueExpression;
+ }
+ } else {
+ return eachExpression;
+ }
+ }
+ va_end(argumentList);
+
+ return nil;
+}
+
+
+/**
+ A placeholder for a catch-all method that evaluates an arbitrary number of
+ arguments as an expression according to the Mapbox Style Specification’s
+ expression language.
+ */
+- (id)MGL_FUNCTION:(id)firstArgument, ... {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Mapbox GL function expressions lack underlying Objective-C implementations."];
+ return nil;
+}
+
+@end
+
@implementation NSExpression (MGLPrivateAdditions)
- (std::vector<mbgl::Value>)mgl_aggregateMBGLValue {
@@ -159,6 +389,112 @@
return {};
}
+// Selectors of functions that can contain tokens in arguments.
+static NSArray * const MGLTokenizedFunctions = @[
+ @"mgl_interpolateWithCurveType:parameters:stops:",
+ @"mgl_interpolate:withCurveType:parameters:stops:",
+ @"mgl_stepWithMinimum:stops:",
+ @"mgl_step:from:stops:",
+];
+
+/**
+ Returns a copy of the given collection with tokens replaced by key path
+ expressions.
+
+ If no replacements take place, this method returns the original collection.
+ */
+NS_ARRAY_OF(NSExpression *) *MGLCollectionByReplacingTokensWithKeyPaths(NS_ARRAY_OF(NSExpression *) *collection) {
+ __block NSMutableArray *upgradedCollection;
+ [collection enumerateObjectsUsingBlock:^(NSExpression * _Nonnull item, NSUInteger idx, BOOL * _Nonnull stop) {
+ NSExpression *upgradedItem = item.mgl_expressionByReplacingTokensWithKeyPaths;
+ if (upgradedItem != item) {
+ if (!upgradedCollection) {
+ upgradedCollection = [collection mutableCopy];
+ }
+ upgradedCollection[idx] = upgradedItem;
+ }
+ }];
+ return upgradedCollection ?: collection;
+};
+
+/**
+ Returns a copy of the given stop dictionary with tokens replaced by key path
+ expressions.
+
+ If no replacements take place, this method returns the original stop
+ dictionary.
+ */
+NS_DICTIONARY_OF(NSNumber *, NSExpression *) *MGLStopDictionaryByReplacingTokensWithKeyPaths(NS_DICTIONARY_OF(NSNumber *, NSExpression *) *stops) {
+ __block NSMutableDictionary *upgradedStops;
+ [stops enumerateKeysAndObjectsUsingBlock:^(id _Nonnull zoomLevel, NSExpression * _Nonnull value, BOOL * _Nonnull stop) {
+ if (![value isKindOfClass:[NSExpression class]]) {
+ value = [NSExpression expressionForConstantValue:value];
+ }
+ NSExpression *upgradedValue = value.mgl_expressionByReplacingTokensWithKeyPaths;
+ if (upgradedValue != value) {
+ if (!upgradedStops) {
+ upgradedStops = [stops mutableCopy];
+ }
+ upgradedStops[zoomLevel] = upgradedValue;
+ }
+ }];
+ return upgradedStops ?: stops;
+};
+
+- (NSExpression *)mgl_expressionByReplacingTokensWithKeyPaths {
+ switch (self.expressionType) {
+ case NSConstantValueExpressionType: {
+ NSString *constantValue = self.constantValue;
+ if ([constantValue isKindOfClass:[NSString class]] &&
+ [constantValue containsString:@"{"] && [constantValue containsString:@"}"]) {
+ NSMutableArray *components = [NSMutableArray array];
+ NSScanner *scanner = [NSScanner scannerWithString:constantValue];
+ scanner.charactersToBeSkipped = nil;
+ while (!scanner.isAtEnd) {
+ NSString *string;
+ if ([scanner scanUpToString:@"{" intoString:&string]) {
+ [components addObject:[NSExpression expressionForConstantValue:string]];
+ }
+
+ NSString *token;
+ if ([scanner scanString:@"{" intoString:NULL]
+ && [scanner scanUpToString:@"}" intoString:&token]
+ && [scanner scanString:@"}" intoString:NULL]) {
+ [components addObject:[NSExpression expressionForKeyPath:token]];
+ }
+ }
+ if (components.count == 1) {
+ return components.firstObject;
+ }
+ return [NSExpression expressionForFunction:@"mgl_join:"
+ arguments:@[[NSExpression expressionForAggregate:components]]];
+ }
+ NSDictionary *stops = self.constantValue;
+ if ([stops isKindOfClass:[NSDictionary class]]) {
+ NSDictionary *localizedStops = MGLStopDictionaryByReplacingTokensWithKeyPaths(stops);
+ if (localizedStops != stops) {
+ return [NSExpression expressionForConstantValue:localizedStops];
+ }
+ }
+ return self;
+ }
+
+ case NSFunctionExpressionType: {
+ if ([MGLTokenizedFunctions containsObject:self.function]) {
+ NSArray *arguments = self.arguments;
+ NSArray *localizedArguments = MGLCollectionByReplacingTokensWithKeyPaths(arguments);
+ if (localizedArguments != arguments) {
+ return [NSExpression expressionForFunction:self.operand selectorName:self.function arguments:localizedArguments];
+ }
+ }
+ return self;
+ }
+
+ default:
+ return self;
+ }
+}
+
@end
@implementation NSObject (MGLExpressionAdditions)
@@ -258,6 +594,12 @@
return [self valueForKeyPath:@"mgl_jsonExpressionObject"];
}
+- (id)mgl_coalesce {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Coalesce expressions lack underlying Objective-C implementations."];
+ return nil;
+}
+
@end
@implementation NSDictionary (MGLExpressionAdditions)
@@ -271,6 +613,13 @@
return expressionObject;
}
+- (id)mgl_has:(id)element {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Has expressions lack underlying Objective-C implementations."];
+ return nil;
+
+}
+
@end
@implementation NSExpression (MGLExpressionAdditions)
@@ -281,23 +630,91 @@
return self;
}
+- (id)mgl_has:(id)element {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Has expressions lack underlying Objective-C implementations."];
+ return nil;
+}
+
@end
@implementation NSExpression (MGLAdditions)
++ (NSExpression *)zoomLevelVariableExpression {
+ return [NSExpression expressionForVariable:@"zoomLevel"];
+}
+
++ (NSExpression *)heatmapDensityVariableExpression {
+ return [NSExpression expressionForVariable:@"heatmapDensity"];
+}
+
++ (NSExpression *)geometryTypeVariableExpression {
+ return [NSExpression expressionForVariable:@"geometryType"];
+}
+
++ (NSExpression *)featureIdentifierVariableExpression {
+ return [NSExpression expressionForVariable:@"featureIdentifier"];
+}
+
++ (NSExpression *)featureAttributesVariableExpression {
+ return [NSExpression expressionForVariable:@"featureAttributes"];
+}
+
++ (NSExpression *)featurePropertiesVariableExpression {
+ return [self featureAttributesVariableExpression];
+}
+
++ (instancetype)mgl_expressionForConditional:(nonnull NSPredicate *)conditionPredicate trueExpression:(nonnull NSExpression *)trueExpression falseExpresssion:(nonnull NSExpression *)falseExpression {
+ if (@available(iOS 9.0, *)) {
+ return [NSExpression expressionForConditional:conditionPredicate trueExpression:trueExpression falseExpression:falseExpression];
+ } else {
+ return [NSExpression expressionForFunction:@"MGL_IF" arguments:@[[NSExpression expressionWithFormat:@"%@", conditionPredicate], trueExpression, falseExpression]];
+ }
+}
+
++ (instancetype)mgl_expressionForSteppingExpression:(nonnull NSExpression *)steppingExpression fromExpression:(nonnull NSExpression *)minimumExpression stops:(nonnull NSExpression *)stops {
+ return [NSExpression expressionForFunction:@"mgl_step:from:stops:"
+ arguments:@[steppingExpression, minimumExpression, stops]];
+}
+
++ (instancetype)mgl_expressionForInterpolatingExpression:(nonnull NSExpression *)inputExpression withCurveType:(nonnull MGLExpressionInterpolationMode)curveType parameters:(nullable NSExpression *)parameters stops:(nonnull NSExpression *)stops {
+ NSExpression *sanitizeParams = parameters ? parameters : [NSExpression expressionForConstantValue:nil];
+ return [NSExpression expressionForFunction:@"mgl_interpolate:withCurveType:parameters:stops:"
+ arguments:@[inputExpression, [NSExpression expressionForConstantValue:curveType], sanitizeParams, stops]];
+}
+
++ (instancetype)mgl_expressionForMatchingExpression:(nonnull NSExpression *)inputExpression inDictionary:(nonnull NSDictionary<NSExpression *, NSExpression *> *)matchedExpressions defaultExpression:(nonnull NSExpression *)defaultExpression {
+ NSMutableArray *optionsArray = [NSMutableArray arrayWithObjects:inputExpression, nil];
+
+ NSEnumerator *matchEnumerator = matchedExpressions.keyEnumerator;
+ while (NSExpression *key = matchEnumerator.nextObject) {
+ [optionsArray addObject:key];
+ [optionsArray addObject:[matchedExpressions objectForKey:key]];
+ }
+
+ [optionsArray addObject:defaultExpression];
+ return [NSExpression expressionForFunction:@"MGL_MATCH"
+ arguments:optionsArray];
+}
+
+- (instancetype)mgl_expressionByAppendingExpression:(nonnull NSExpression *)expression {
+ NSExpression *subexpression = [NSExpression expressionForAggregate:@[self, expression]];
+ return [NSExpression expressionForFunction:@"mgl_join:" arguments:@[subexpression]];
+}
+
static NSDictionary<NSString *, NSString *> *MGLFunctionNamesByExpressionOperator;
static NSDictionary<NSString *, NSString *> *MGLExpressionOperatorsByFunctionNames;
NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
NSMutableArray *subexpressions = [NSMutableArray arrayWithCapacity:objects.count];
for (id object in objects) {
- NSExpression *expression = [NSExpression mgl_expressionWithJSONObject:object];
+ NSExpression *expression = [NSExpression expressionWithMGLJSONObject:object];
[subexpressions addObject:expression];
}
return subexpressions;
}
-+ (instancetype)mgl_expressionWithJSONObject:(id)object {
++ (instancetype)expressionWithMGLJSONObject:(id)object {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
MGLFunctionNamesByExpressionOperator = @{
@@ -309,9 +726,21 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
@"sqrt": @"sqrt:",
@"log10": @"log:",
@"ln": @"ln:",
+ @"abs": @"abs:",
+ @"round": @"mgl_round:",
+ @"acos" : @"mgl_acos:",
+ @"cos" : @"mgl_cos:",
+ @"asin" : @"mgl_asin:",
+ @"sin" : @"mgl_sin:",
+ @"atan" : @"mgl_atan:",
+ @"tan" : @"mgl_tan:",
+ @"log2" : @"mgl_log2:",
+ @"floor": @"floor:",
+ @"ceil": @"ceiling:",
@"^": @"raise:toPower:",
@"upcase": @"uppercase:",
@"downcase": @"lowercase:",
+ @"let": @"MGL_LET",
};
});
@@ -329,7 +758,7 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
if ([object isKindOfClass:[NSDictionary class]]) {
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:[object count]];
[object enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
- dictionary[key] = [NSExpression mgl_expressionWithJSONObject:obj];
+ dictionary[key] = [NSExpression expressionWithMGLJSONObject:obj];
}];
return [NSExpression expressionForConstantValue:dictionary];
}
@@ -358,31 +787,45 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
if ([argumentObjects.firstObject isKindOfClass:[NSArray class]]) {
return [NSExpression expressionForAggregate:MGLSubexpressionsWithJSONObjects(argumentObjects.firstObject)];
}
- return [NSExpression mgl_expressionWithJSONObject:argumentObjects.firstObject];
+ return [NSExpression expressionWithMGLJSONObject:argumentObjects.firstObject];
} else if ([op isEqualToString:@"to-boolean"]) {
- NSExpression *operand = [NSExpression mgl_expressionWithJSONObject:argumentObjects.firstObject];
+ NSExpression *operand = [NSExpression expressionWithMGLJSONObject:argumentObjects.firstObject];
return [NSExpression expressionForFunction:operand selectorName:@"boolValue" arguments:@[]];
- } else if ([op isEqualToString:@"to-number"]) {
- NSExpression *operand = [NSExpression mgl_expressionWithJSONObject:argumentObjects.firstObject];
+ } else if ([op isEqualToString:@"to-number"] || [op isEqualToString:@"number"]) {
+ NSExpression *operand = [NSExpression expressionWithMGLJSONObject:argumentObjects.firstObject];
+ if (argumentObjects.count == 1) {
+ return [NSExpression expressionWithFormat:@"CAST(%@, 'NSNumber')", operand];
+ }
argumentObjects = [argumentObjects subarrayWithRange:NSMakeRange(1, argumentObjects.count - 1)];
NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects);
return [NSExpression expressionForFunction:operand selectorName:@"mgl_numberWithFallbackValues:" arguments:subexpressions];
- } else if ([op isEqualToString:@"to-string"]) {
- NSExpression *operand = [NSExpression mgl_expressionWithJSONObject:argumentObjects.firstObject];
- return [NSExpression expressionForFunction:operand selectorName:@"stringValue" arguments:@[]];
+ } else if ([op isEqualToString:@"to-string"] || [op isEqualToString:@"string"]) {
+ NSExpression *operand = [NSExpression expressionWithMGLJSONObject:argumentObjects.firstObject];
+ return [NSExpression expressionWithFormat:@"CAST(%@, 'NSString')", operand];
} else if ([op isEqualToString:@"get"]) {
if (argumentObjects.count == 2) {
- NSExpression *operand = [NSExpression mgl_expressionWithJSONObject:argumentObjects.lastObject];
+ NSExpression *operand = [NSExpression expressionWithMGLJSONObject:argumentObjects.lastObject];
if ([argumentObjects.firstObject isKindOfClass:[NSString class]]) {
return [NSExpression expressionWithFormat:@"%@.%K", operand, argumentObjects.firstObject];
}
- NSExpression *key = [NSExpression mgl_expressionWithJSONObject:argumentObjects.firstObject];
+ NSExpression *key = [NSExpression expressionWithMGLJSONObject:argumentObjects.firstObject];
return [NSExpression expressionWithFormat:@"%@.%@", operand, key];
}
return [NSExpression expressionForKeyPath:argumentObjects.firstObject];
} else if ([op isEqualToString:@"length"]) {
NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects);
- return [NSExpression expressionForFunction:@"count:" arguments:@[subexpressions.firstObject]];
+ NSString *function = @"count:";
+ if ([subexpressions.firstObject expressionType] == NSConstantValueExpressionType
+ && [[subexpressions.firstObject constantValue] isKindOfClass:[NSString class]]) {
+ function = @"length:";
+ }
+ return [NSExpression expressionForFunction:function arguments:@[subexpressions.firstObject]];
+ } else if ([op isEqualToString:@"rgb"]) {
+ NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects);
+ return [NSExpression mgl_expressionForRGBComponents:subexpressions];
+ } else if ([op isEqualToString:@"rgba"]) {
+ NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects);
+ return [NSExpression mgl_expressionForRGBAComponents:subexpressions];
} else if ([op isEqualToString:@"min"]) {
NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects);
NSExpression *subexpression = [NSExpression expressionForAggregate:subexpressions];
@@ -397,39 +840,47 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
return [NSExpression expressionForConstantValue:@(M_PI)];
} else if ([op isEqualToString:@"concat"]) {
NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects);
- NSExpression *operand = subexpressions.firstObject;
- subexpressions = [subexpressions subarrayWithRange:NSMakeRange(1, subexpressions.count - 1)];
- return [NSExpression expressionForFunction:operand selectorName:@"stringByAppendingString:" arguments:subexpressions];
+ NSExpression *subexpression = [NSExpression expressionForAggregate:subexpressions];
+ return [NSExpression expressionForFunction:@"mgl_join:" arguments:@[subexpression]];
+ } else if ([op isEqualToString:@"at"]) {
+ NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects);
+ NSExpression *index = subexpressions.firstObject;
+ NSExpression *operand = subexpressions[1];
+ return [NSExpression expressionForFunction:@"objectFrom:withIndex:" arguments:@[operand, index]];
+ } else if ([op isEqualToString:@"has"]) {
+ NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(argumentObjects);
+ NSExpression *operand = argumentObjects.count > 1 ? subexpressions[1] : [NSExpression expressionForEvaluatedObject];
+ NSExpression *key = subexpressions.firstObject;
+ return [NSExpression expressionForFunction:@"mgl_does:have:" arguments:@[operand, key]];
} else if ([op isEqualToString:@"interpolate"]) {
NSArray *interpolationOptions = argumentObjects.firstObject;
NSString *curveType = interpolationOptions.firstObject;
- NSExpression *curveTypeExpression = [NSExpression mgl_expressionWithJSONObject:curveType];
+ NSExpression *curveTypeExpression = [NSExpression expressionWithMGLJSONObject:curveType];
id curveParameters;
if ([curveType isEqual:@"exponential"]) {
curveParameters = interpolationOptions[1];
} else if ([curveType isEqualToString:@"cubic-bezier"]) {
curveParameters = @[@"literal", [interpolationOptions subarrayWithRange:NSMakeRange(1, 4)]];
}
- NSExpression *curveParameterExpression = [NSExpression mgl_expressionWithJSONObject:curveParameters];
+ NSExpression *curveParameterExpression = [NSExpression expressionWithMGLJSONObject:curveParameters];
argumentObjects = [argumentObjects subarrayWithRange:NSMakeRange(1, argumentObjects.count - 1)];
- NSExpression *operand = [NSExpression mgl_expressionWithJSONObject:argumentObjects.firstObject];
+ NSExpression *inputExpression = [NSExpression expressionWithMGLJSONObject:argumentObjects.firstObject];
NSArray *stopExpressions = [argumentObjects subarrayWithRange:NSMakeRange(1, argumentObjects.count - 1)];
NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:stopExpressions.count / 2];
NSEnumerator *stopEnumerator = stopExpressions.objectEnumerator;
while (NSNumber *key = stopEnumerator.nextObject) {
NSExpression *valueExpression = stopEnumerator.nextObject;
- stops[key] = [NSExpression mgl_expressionWithJSONObject:valueExpression];
+ stops[key] = [NSExpression expressionWithMGLJSONObject:valueExpression];
}
NSExpression *stopExpression = [NSExpression expressionForConstantValue:stops];
- return [NSExpression expressionForFunction:operand
- selectorName:@"mgl_interpolateWithCurveType:parameters:stops:"
- arguments:@[curveTypeExpression, curveParameterExpression, stopExpression]];
+ return [NSExpression expressionForFunction:@"mgl_interpolate:withCurveType:parameters:stops:"
+ arguments:@[inputExpression, curveTypeExpression, curveParameterExpression, stopExpression]];
} else if ([op isEqualToString:@"step"]) {
- NSExpression *operand = [NSExpression mgl_expressionWithJSONObject:argumentObjects[0]];
+ NSExpression *inputExpression = [NSExpression expressionWithMGLJSONObject:argumentObjects[0]];
NSArray *stopExpressions = [argumentObjects subarrayWithRange:NSMakeRange(1, argumentObjects.count - 1)];
NSExpression *minimum;
if (stopExpressions.count % 2) {
- minimum = [NSExpression mgl_expressionWithJSONObject:stopExpressions.firstObject];
+ minimum = [NSExpression expressionWithMGLJSONObject:stopExpressions.firstObject];
stopExpressions = [stopExpressions subarrayWithRange:NSMakeRange(1, stopExpressions.count - 1)];
}
NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:stopExpressions.count / 2];
@@ -437,47 +888,66 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
while (NSNumber *key = stopEnumerator.nextObject) {
NSExpression *valueExpression = stopEnumerator.nextObject;
if (minimum) {
- stops[key] = [NSExpression mgl_expressionWithJSONObject:valueExpression];
+ stops[key] = [NSExpression expressionWithMGLJSONObject:valueExpression];
} else {
- minimum = [NSExpression mgl_expressionWithJSONObject:valueExpression];
+ minimum = [NSExpression expressionWithMGLJSONObject:valueExpression];
}
}
NSExpression *stopExpression = [NSExpression expressionForConstantValue:stops];
- return [NSExpression expressionForFunction:operand
- selectorName:@"mgl_stepWithMinimum:stops:"
- arguments:@[minimum, stopExpression]];
+ return [NSExpression expressionForFunction:@"mgl_step:from:stops:"
+ arguments:@[inputExpression, minimum, stopExpression]];
} else if ([op isEqualToString:@"zoom"]) {
- return [NSExpression expressionForVariable:@"zoomLevel"];
+ return NSExpression.zoomLevelVariableExpression;
} else if ([op isEqualToString:@"heatmap-density"]) {
- return [NSExpression expressionForVariable:@"heatmapDensity"];
- } else if ([op isEqualToString:@"let"]) {
- NSExpression *operand = [NSExpression mgl_expressionWithJSONObject:argumentObjects.lastObject];
- NSArray *bindingObjects = [argumentObjects subarrayWithRange:NSMakeRange(0, argumentObjects.count - 1)];
- NSMutableDictionary *context = [NSMutableDictionary dictionaryWithCapacity:bindingObjects.count / 2];
- NSEnumerator *bindingEnumerator = bindingObjects.objectEnumerator;
- while (NSString *key = bindingEnumerator.nextObject) {
- context[key] = [NSExpression mgl_expressionWithJSONObject:bindingEnumerator.nextObject];
- }
- return [NSExpression expressionForFunction:operand
- selectorName:@"mgl_expressionWithContext:"
- arguments:@[[NSExpression expressionForConstantValue:context]]];
+ return NSExpression.heatmapDensityVariableExpression;
+ } else if ([op isEqualToString:@"geometry-type"]) {
+ return NSExpression.geometryTypeVariableExpression;
+ } else if ([op isEqualToString:@"id"]) {
+ return NSExpression.featureIdentifierVariableExpression;
+ } else if ([op isEqualToString:@"properties"]) {
+ return NSExpression.featureAttributesVariableExpression;
} else if ([op isEqualToString:@"var"]) {
return [NSExpression expressionForVariable:argumentObjects.firstObject];
} else if ([op isEqualToString:@"case"]) {
- NSPredicate *conditional = [NSPredicate mgl_predicateWithJSONObject:argumentObjects.firstObject];
- NSExpression *trueExpression = [NSExpression mgl_expressionWithJSONObject:argumentObjects[1]];
- NSExpression *falseExpression;
- if (argumentObjects.count > 3) {
- NSArray *falseObjects = [@[@"case"] arrayByAddingObjectsFromArray:
- [argumentObjects subarrayWithRange:NSMakeRange(2, argumentObjects.count - 2)]];
- falseExpression = [NSExpression mgl_expressionWithJSONObject:falseObjects];
- } else {
- falseExpression = [NSExpression mgl_expressionWithJSONObject:argumentObjects[2]];
+ NSMutableArray *arguments = [NSMutableArray array];
+
+ for (NSUInteger index = 0; index < argumentObjects.count; index++) {
+ if (index % 2 == 0 && index != argumentObjects.count - 1) {
+ NSPredicate *predicate = [NSPredicate mgl_predicateWithJSONObject:argumentObjects[index]];
+ NSExpression *argument = [NSExpression expressionForConstantValue:predicate];
+ [arguments addObject:argument];
+ } else {
+ [arguments addObject:[NSExpression expressionWithMGLJSONObject:argumentObjects[index]]];
+ }
}
- return [NSExpression expressionForConditional:conditional trueExpression:trueExpression falseExpression:falseExpression];
+
+ if (@available(iOS 9.0, *)) {
+ if (arguments.count == 3) {
+ NSPredicate *conditional = [arguments.firstObject constantValue];
+ return [NSExpression expressionForConditional:conditional trueExpression:arguments[1] falseExpression:arguments[2]];
+ }
+ }
+ return [NSExpression expressionForFunction:@"MGL_IF" arguments:arguments];
+ } else if ([op isEqualToString:@"match"]) {
+ NSMutableArray *optionsArray = [NSMutableArray array];
+ NSEnumerator *optionsEnumerator = argumentObjects.objectEnumerator;
+ while (id object = optionsEnumerator.nextObject) {
+ NSExpression *option = [NSExpression expressionWithMGLJSONObject:object];
+ [optionsArray addObject:option];
+ }
+
+ return [NSExpression expressionForFunction:@"MGL_MATCH"
+ arguments:optionsArray];
+ } else if ([op isEqualToString:@"coalesce"]) {
+ NSMutableArray *expressions = [NSMutableArray array];
+ for (id operand in argumentObjects) {
+ [expressions addObject:[NSExpression expressionWithMGLJSONObject:operand]];
+ }
+
+ return [NSExpression expressionWithFormat:@"mgl_coalesce(%@)", expressions];
} else {
- [NSException raise:NSInvalidArgumentException
- format:@"Expression operator %@ not yet implemented.", op];
+ NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(array);
+ return [NSExpression expressionForFunction:@"MGL_FUNCTION" arguments:subexpressions];
}
}
@@ -500,8 +970,23 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
@"log:": @"log10",
@"ln:": @"ln",
@"raise:toPower:": @"^",
+ @"ceiling:": @"ceil",
+ @"abs:": @"abs",
+ @"floor:": @"floor",
@"uppercase:": @"upcase",
@"lowercase:": @"downcase",
+ @"length:": @"length",
+ @"mgl_round:": @"round",
+ @"mgl_acos:" : @"acos",
+ @"mgl_cos:" : @"cos",
+ @"mgl_asin:" : @"asin",
+ @"mgl_sin:" : @"sin",
+ @"mgl_atan:" : @"atan",
+ @"mgl_tan:" : @"tan",
+ @"mgl_log2:" : @"log2",
+ // Vararg aftermarket expressions need to be declared with an explicit and implicit first argument.
+ @"MGL_LET": @"let",
+ @"MGL_LET:": @"let",
};
});
@@ -513,6 +998,15 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
if ([self.variable isEqualToString:@"zoomLevel"]) {
return @[@"zoom"];
}
+ if ([self.variable isEqualToString:@"geometryType"]) {
+ return @[@"geometry-type"];
+ }
+ if ([self.variable isEqualToString:@"featureIdentifier"]) {
+ return @[@"id"];
+ }
+ if ([self.variable isEqualToString:@"featureAttributes"]) {
+ return @[@"properties"];
+ }
return @[@"var", self.variable];
}
@@ -573,7 +1067,7 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
if (op) {
NSArray *arguments = self.arguments.mgl_jsonExpressionObject;
return [@[op] arrayByAddingObjectsFromArray:arguments];
- } else if ([function isEqualToString:@"valueForKeyPath:"]) {
+ } else if ([function isEqualToString:@"valueForKey:"] || [function isEqualToString:@"valueForKeyPath:"]) {
return @[@"get", self.arguments.firstObject.mgl_jsonExpressionObject, self.operand.mgl_jsonExpressionObject];
} else if ([function isEqualToString:@"average:"]) {
NSExpression *sum = [NSExpression expressionForFunction:@"sum:" arguments:self.arguments];
@@ -593,24 +1087,21 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
return [@[@"max"] arrayByAddingObjectsFromArray:arguments];
} else if ([function isEqualToString:@"exp:"]) {
return [NSExpression expressionForFunction:@"raise:toPower:" arguments:@[@(M_E), self.arguments.firstObject]].mgl_jsonExpressionObject;
- } else if ([function isEqualToString:@"ceiling:"]) {
- return [NSExpression expressionWithFormat:@"trunc:(%@) + TERNARY(modulus:by:(%@, 1) > 0, 1, 0)",
- self.arguments.firstObject, self.arguments.firstObject].mgl_jsonExpressionObject;
} else if ([function isEqualToString:@"trunc:"]) {
return [NSExpression expressionWithFormat:@"%@ - modulus:by:(%@, 1)",
self.arguments.firstObject, self.arguments.firstObject].mgl_jsonExpressionObject;
- } else if ([function isEqualToString:@"abs:"]) {
- return [NSExpression expressionWithFormat:@"%@ * TERNARY(%@ > 0, 1, -1)",
- self.arguments.firstObject, self.arguments.firstObject].mgl_jsonExpressionObject;
- } else if ([function isEqualToString:@"floor:"]) {
- return [NSExpression expressionWithFormat:@"trunc:(%@) - TERNARY(modulus:by:(%@, 1) < 0, 1, 0)",
- self.arguments.firstObject, self.arguments.firstObject].mgl_jsonExpressionObject;
+ } else if ([function isEqualToString:@"mgl_join:"]) {
+ NSArray *arguments = [self.arguments.firstObject.collection valueForKeyPath:@"mgl_jsonExpressionObject"];
+ return [@[@"concat"] arrayByAddingObjectsFromArray:arguments];
} else if ([function isEqualToString:@"stringByAppendingString:"]) {
NSArray *arguments = self.arguments.mgl_jsonExpressionObject;
return [@[@"concat", self.operand.mgl_jsonExpressionObject] arrayByAddingObjectsFromArray:arguments];
+ } else if ([function isEqualToString:@"objectFrom:withIndex:"]) {
+ return @[@"at", self.arguments[1].mgl_jsonExpressionObject, self.arguments[0].mgl_jsonExpressionObject];
} else if ([function isEqualToString:@"boolValue"]) {
return @[@"to-boolean", self.operand.mgl_jsonExpressionObject];
- } else if ([function isEqualToString:@"mgl_numberWithFallbackValues:"] ||
+ } else if ([function isEqualToString:@"mgl_number"] ||
+ [function isEqualToString:@"mgl_numberWithFallbackValues:"] ||
[function isEqualToString:@"decimalValue"] ||
[function isEqualToString:@"floatValue"] ||
[function isEqualToString:@"doubleValue"]) {
@@ -620,40 +1111,15 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
return @[@"to-string", self.operand.mgl_jsonExpressionObject];
} else if ([function isEqualToString:@"noindex:"]) {
return self.arguments.firstObject.mgl_jsonExpressionObject;
- } else if ([function isEqualToString:@"mgl_interpolateWithCurveType:parameters:stops:"]) {
- if (self.arguments.count < 3) {
- [NSException raise:NSInvalidArgumentException format:
- @"Too few arguments to ‘mgl_interpolateWithCurveType:parameters:stops:’ function; expected 3 arguments."];
- } else if (self.arguments.count > 3) {
- [NSException raise:NSInvalidArgumentException format:
- @"%lu unexpected arguments to ‘mgl_interpolateWithCurveType:parameters:stops:’ function; expected 3 arguments.",
- self.arguments.count - 3];
- }
- NSString *curveType = self.arguments.firstObject.constantValue;
- NSMutableArray *interpolationArray = [NSMutableArray arrayWithObject:curveType];
- if ([curveType isEqualToString:@"exponential"]) {
- id base = [self.arguments[1] mgl_jsonExpressionObject];
- [interpolationArray addObject:base];
- } else if ([curveType isEqualToString:@"cubic-bezier"]) {
- NSArray *controlPoints = [self.arguments[1].collection mgl_jsonExpressionObject];
- [interpolationArray addObjectsFromArray:controlPoints];
- }
- NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"interpolate", interpolationArray, self.operand.mgl_jsonExpressionObject, nil];
- NSDictionary<NSNumber *, NSExpression *> *stops = self.arguments[2].constantValue;
- for (NSNumber *key in [stops.allKeys sortedArrayUsingSelector:@selector(compare:)]) {
- [expressionObject addObject:key];
- [expressionObject addObject:[stops[key] mgl_jsonExpressionObject]];
- }
- return expressionObject;
- } else if ([function isEqualToString:@"mgl_stepWithMinimum:stops:"]) {
- id minimum = self.arguments.firstObject.mgl_jsonExpressionObject;
- NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"step", self.operand.mgl_jsonExpressionObject, minimum, nil];
- NSDictionary<NSNumber *, NSExpression *> *stops = self.arguments[1].constantValue;
- for (NSNumber *key in [stops.allKeys sortedArrayUsingSelector:@selector(compare:)]) {
- [expressionObject addObject:key];
- [expressionObject addObject:[stops[key] mgl_jsonExpressionObject]];
- }
- return expressionObject;
+ } else if ([function isEqualToString:@"mgl_does:have:"] ||
+ [function isEqualToString:@"mgl_has:"]) {
+ return self.mgl_jsonHasExpressionObject;
+ } else if ([function isEqualToString:@"mgl_interpolate:withCurveType:parameters:stops:"]
+ || [function isEqualToString:@"mgl_interpolateWithCurveType:parameters:stops:"]) {
+ return self.mgl_jsonInterpolationExpressionObject;
+ } else if ([function isEqualToString:@"mgl_step:from:stops:"]
+ || [function isEqualToString:@"mgl_stepWithMinimum:stops:"]) {
+ return self.mgl_jsonStepExpressionObject;
} else if ([function isEqualToString:@"mgl_expressionWithContext:"]) {
id context = self.arguments.firstObject;
if ([context isKindOfClass:[NSExpression class]]) {
@@ -666,6 +1132,31 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
}];
[expressionObject addObject:self.operand.mgl_jsonExpressionObject];
return expressionObject;
+ } else if ([function isEqualToString:@"MGL_IF"] ||
+ [function isEqualToString:@"mgl_if:"]) {
+ return self.mgl_jsonIfExpressionObject;
+ } else if ([function isEqualToString:@"MGL_MATCH"] ||
+ [function isEqualToString:@"mgl_match:"]) {
+ return self.mgl_jsonMatchExpressionObject;
+ } else if ([function isEqualToString:@"mgl_coalesce:"] ||
+ [function isEqualToString:@"mgl_coalesce"]) {
+
+ return self.mgl_jsonCoalesceExpressionObject;
+ } else if ([function isEqualToString:@"castObject:toType:"]) {
+ id object = self.arguments.firstObject.mgl_jsonExpressionObject;
+ NSString *type = self.arguments[1].mgl_jsonExpressionObject;
+ if ([type isEqualToString:@"NSString"]) {
+ return @[@"to-string", object];
+ } else if ([type isEqualToString:@"NSNumber"]) {
+ return @[@"to-number", object];
+ }
+ [NSException raise:NSInvalidArgumentException
+ format:@"Casting expression to %@ not yet implemented.", type];
+ } else if ([function isEqualToString:@"MGL_FUNCTION"]) {
+ return self.arguments.mgl_jsonExpressionObject;
+ } else if (op == [MGLColor class] && [function isEqualToString:@"colorWithRed:green:blue:alpha:"]) {
+ NSArray *arguments = self.arguments.mgl_jsonExpressionObject;
+ return [@[@"rgba"] arrayByAddingObjectsFromArray:arguments];
} else if ([function isEqualToString:@"median:"] ||
[function isEqualToString:@"mode:"] ||
[function isEqualToString:@"stddev:"] ||
@@ -690,7 +1181,17 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
}
case NSConditionalExpressionType: {
- NSMutableArray *arguments = [NSMutableArray arrayWithObjects:self.predicate.mgl_jsonExpressionObject, self.trueExpression.mgl_jsonExpressionObject, nil];
+ NSMutableArray *arguments = [NSMutableArray arrayWithObjects:self.predicate.mgl_jsonExpressionObject, nil];
+
+ if (self.trueExpression.expressionType == NSConditionalExpressionType) {
+ // Fold nested conditionals into a single case expression.
+ NSArray *trueArguments = self.trueExpression.mgl_jsonExpressionObject;
+ trueArguments = [trueArguments subarrayWithRange:NSMakeRange(1, trueArguments.count - 1)];
+ [arguments addObjectsFromArray:trueArguments];
+ } else {
+ [arguments addObject:self.trueExpression.mgl_jsonExpressionObject];
+ }
+
if (self.falseExpression.expressionType == NSConditionalExpressionType) {
// Fold nested conditionals into a single case expression.
NSArray *falseArguments = self.falseExpression.mgl_jsonExpressionObject;
@@ -734,4 +1235,243 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
return nil;
}
+- (id)mgl_jsonInterpolationExpressionObject {
+ NSUInteger expectedArgumentCount = [self.function componentsSeparatedByString:@":"].count - 1;
+ if (self.arguments.count < expectedArgumentCount) {
+ [NSException raise:NSInvalidArgumentException format:
+ @"Too few arguments to ‘%@’ function; expected %lu arguments.",
+ self.function, expectedArgumentCount];
+ } else if (self.arguments.count > expectedArgumentCount) {
+ [NSException raise:NSInvalidArgumentException format:
+ @"%lu unexpected arguments to ‘%@’ function; expected %lu arguments.",
+ self.arguments.count - expectedArgumentCount, self.function, expectedArgumentCount];
+ }
+
+ BOOL isAftermarketFunction = [self.function isEqualToString:@"mgl_interpolate:withCurveType:parameters:stops:"];
+ NSUInteger curveTypeIndex = isAftermarketFunction ? 1 : 0;
+ NSString *curveType = self.arguments[curveTypeIndex].constantValue;
+ NSMutableArray *interpolationArray = [NSMutableArray arrayWithObject:curveType];
+ if ([curveType isEqualToString:@"exponential"]) {
+ id base = [self.arguments[curveTypeIndex + 1] mgl_jsonExpressionObject];
+ [interpolationArray addObject:base];
+ } else if ([curveType isEqualToString:@"cubic-bezier"]) {
+ NSArray *controlPoints = [self.arguments[curveTypeIndex + 1].collection mgl_jsonExpressionObject];
+ [interpolationArray addObjectsFromArray:controlPoints];
+ }
+ NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"interpolate", interpolationArray, nil];
+ [expressionObject addObject:(isAftermarketFunction ? self.arguments.firstObject : self.operand).mgl_jsonExpressionObject];
+ NSDictionary<NSNumber *, NSExpression *> *stops = self.arguments[curveTypeIndex + 2].constantValue;
+ for (NSNumber *key in [stops.allKeys sortedArrayUsingSelector:@selector(compare:)]) {
+ [expressionObject addObject:key];
+ [expressionObject addObject:[stops[key] mgl_jsonExpressionObject]];
+ }
+ return expressionObject;
+}
+
+- (id)mgl_jsonStepExpressionObject {
+ BOOL isAftermarketFunction = [self.function isEqualToString:@"mgl_step:from:stops:"];
+ NSUInteger minimumIndex = isAftermarketFunction ? 1 : 0;
+ id minimum = self.arguments[minimumIndex].mgl_jsonExpressionObject;
+ NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"step", (isAftermarketFunction ? self.arguments.firstObject : self.operand).mgl_jsonExpressionObject, minimum, nil];
+ NSDictionary<NSNumber *, NSExpression *> *stops = self.arguments[minimumIndex + 1].constantValue;
+ for (NSNumber *key in [stops.allKeys sortedArrayUsingSelector:@selector(compare:)]) {
+ [expressionObject addObject:key];
+ [expressionObject addObject:[stops[key] mgl_jsonExpressionObject]];
+ }
+ return expressionObject;
+}
+
+- (id)mgl_jsonMatchExpressionObject {
+ BOOL isAftermarketFunction = [self.function isEqualToString:@"MGL_MATCH"];
+ NSUInteger minimumIndex = isAftermarketFunction ? 1 : 0;
+
+ NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"match", (isAftermarketFunction ? self.arguments.firstObject : self.operand).mgl_jsonExpressionObject, nil];
+ NSArray<NSExpression *> *arguments = isAftermarketFunction ? self.arguments : self.arguments[minimumIndex].constantValue;
+
+ for (NSUInteger index = minimumIndex; index < arguments.count; index++) {
+ [expressionObject addObject:arguments[index].mgl_jsonExpressionObject];
+ }
+
+ return expressionObject;
+}
+
+- (id)mgl_jsonIfExpressionObject {
+ BOOL isAftermarketFunction = [self.function isEqualToString:@"MGL_IF"];
+ NSUInteger minimumIndex = isAftermarketFunction ? 1 : 0;
+ NSExpression *firstCondition;
+ id condition;
+
+ if (isAftermarketFunction) {
+ firstCondition = self.arguments.firstObject;
+ } else {
+ firstCondition = self.operand;
+ }
+
+ if ([firstCondition respondsToSelector:@selector(constantValue)] && [firstCondition.constantValue isKindOfClass:[NSComparisonPredicate class]]) {
+ NSPredicate *predicate = (NSPredicate *)firstCondition.constantValue;
+ condition = predicate.mgl_jsonExpressionObject;
+ } else {
+ condition = firstCondition.mgl_jsonExpressionObject;
+ }
+
+ NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"case", condition, nil];
+ NSArray<NSExpression *> *arguments = isAftermarketFunction ? self.arguments : self.arguments[minimumIndex].constantValue;
+
+ for (NSUInteger index = minimumIndex; index < arguments.count; index++) {
+ if ([arguments[index] respondsToSelector:@selector(constantValue)] && [arguments[index].constantValue isKindOfClass:[NSComparisonPredicate class]]) {
+ NSPredicate *predicate = (NSPredicate *)arguments[index].constantValue;
+ [expressionObject addObject:predicate.mgl_jsonExpressionObject];
+ } else {
+ [expressionObject addObject:arguments[index].mgl_jsonExpressionObject];
+ }
+ }
+
+ return expressionObject;
+}
+
+- (id)mgl_jsonCoalesceExpressionObject {
+ BOOL isAftermarketFunction = [self.function isEqualToString:@"mgl_coalesce:"];
+ NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"coalesce", nil];
+
+ for (NSExpression *expression in (isAftermarketFunction ? self.arguments.firstObject : self.operand).constantValue) {
+ [expressionObject addObject:[expression mgl_jsonExpressionObject]];
+ }
+
+ return expressionObject;
+}
+
+- (id)mgl_jsonHasExpressionObject {
+ BOOL isAftermarketFunction = [self.function isEqualToString:@"mgl_does:have:"];
+ NSExpression *operand = isAftermarketFunction ? self.arguments[0] : self.operand;
+ NSExpression *key = self.arguments[isAftermarketFunction ? 1 : 0];
+
+ NSMutableArray *expressionObject = [NSMutableArray arrayWithObjects:@"has", key.mgl_jsonExpressionObject, nil];
+ if (operand.expressionType != NSEvaluatedObjectExpressionType) {
+ [expressionObject addObject:operand.mgl_jsonExpressionObject];
+ }
+ return expressionObject;
+}
+
+#pragma mark Localization
+
+/**
+ Returns a localized copy of the given collection.
+
+ If no localization takes place, this method returns the original collection.
+ */
+NS_ARRAY_OF(NSExpression *) *MGLLocalizedCollection(NS_ARRAY_OF(NSExpression *) *collection, NSLocale * _Nullable locale) {
+ __block NSMutableArray *localizedCollection;
+ [collection enumerateObjectsUsingBlock:^(NSExpression * _Nonnull item, NSUInteger idx, BOOL * _Nonnull stop) {
+ NSExpression *localizedItem = [item mgl_expressionLocalizedIntoLocale:locale];
+ if (localizedItem != item) {
+ if (!localizedCollection) {
+ localizedCollection = [collection mutableCopy];
+ }
+ localizedCollection[idx] = localizedItem;
+ }
+ }];
+ return localizedCollection ?: collection;
+};
+
+/**
+ Returns a localized copy of the given stop dictionary.
+
+ If no localization takes place, this method returns the original stop
+ dictionary.
+ */
+NS_DICTIONARY_OF(NSNumber *, NSExpression *) *MGLLocalizedStopDictionary(NS_DICTIONARY_OF(NSNumber *, NSExpression *) *stops, NSLocale * _Nullable locale) {
+ __block NSMutableDictionary *localizedStops;
+ [stops enumerateKeysAndObjectsUsingBlock:^(id _Nonnull zoomLevel, NSExpression * _Nonnull value, BOOL * _Nonnull stop) {
+ if (![value isKindOfClass:[NSExpression class]]) {
+ value = [NSExpression expressionForConstantValue:value];
+ }
+ NSExpression *localizedValue = [value mgl_expressionLocalizedIntoLocale:locale];
+ if (localizedValue != value) {
+ if (!localizedStops) {
+ localizedStops = [stops mutableCopy];
+ }
+ localizedStops[zoomLevel] = localizedValue;
+ }
+ }];
+ return localizedStops ?: stops;
+};
+
+- (NSExpression *)mgl_expressionLocalizedIntoLocale:(nullable NSLocale *)locale {
+ switch (self.expressionType) {
+ case NSConstantValueExpressionType: {
+ NSDictionary *stops = self.constantValue;
+ if ([stops isKindOfClass:[NSDictionary class]]) {
+ NSDictionary *localizedStops = MGLLocalizedStopDictionary(stops, locale);
+ if (localizedStops != stops) {
+ return [NSExpression expressionForConstantValue:localizedStops];
+ }
+ }
+ return self;
+ }
+
+ case NSKeyPathExpressionType: {
+ if ([self.keyPath isEqualToString:@"name"] || [self.keyPath hasPrefix:@"name_"]) {
+ NSString *localizedKeyPath = @"name";
+ if (![locale.localeIdentifier isEqualToString:@"mul"]) {
+ NSArray *preferences = locale ? @[locale.localeIdentifier] : [NSLocale preferredLanguages];
+ NSString *preferredLanguage = [MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences];
+ if (preferredLanguage) {
+ localizedKeyPath = [NSString stringWithFormat:@"name_%@", preferredLanguage];
+ }
+ }
+ return [NSExpression expressionForKeyPath:localizedKeyPath];
+ }
+ return self;
+ }
+
+ case NSFunctionExpressionType: {
+ NSExpression *operand = self.operand;
+ NSExpression *localizedOperand = [operand mgl_expressionLocalizedIntoLocale:locale];
+
+ NSArray *arguments = self.arguments;
+ NSArray *localizedArguments = MGLLocalizedCollection(arguments, locale);
+ if (localizedArguments != arguments) {
+ return [NSExpression expressionForFunction:localizedOperand
+ selectorName:self.function
+ arguments:localizedArguments];
+ }
+ if (localizedOperand != operand) {
+ return [NSExpression expressionForFunction:localizedOperand
+ selectorName:self.function
+ arguments:self.arguments];
+ }
+ return self;
+ }
+
+ case NSConditionalExpressionType: {
+ if (@available(iOS 9.0, *)) {
+ NSExpression *trueExpression = self.trueExpression;
+ NSExpression *localizedTrueExpression = [trueExpression mgl_expressionLocalizedIntoLocale:locale];
+ NSExpression *falseExpression = self.falseExpression;
+ NSExpression *localizedFalseExpression = [falseExpression mgl_expressionLocalizedIntoLocale:locale];
+ if (localizedTrueExpression != trueExpression || localizedFalseExpression != falseExpression) {
+ return [NSExpression expressionForConditional:self.predicate
+ trueExpression:localizedTrueExpression
+ falseExpression:localizedFalseExpression];
+ }
+ }
+ return self;
+ }
+
+ case NSAggregateExpressionType: {
+ NSArray *collection = self.collection;
+ if ([collection isKindOfClass:[NSArray class]]) {
+ NSArray *localizedCollection = MGLLocalizedCollection(collection, locale);
+ if (localizedCollection != collection) {
+ return [NSExpression expressionForAggregate:localizedCollection];
+ }
+ }
+ return self;
+ }
+
+ default:
+ return self;
+ }
+}
+
@end
diff --git a/platform/darwin/src/NSExpression+MGLPrivateAdditions.h b/platform/darwin/src/NSExpression+MGLPrivateAdditions.h
index 8d1b4d6af5..a1948f9e45 100644
--- a/platform/darwin/src/NSExpression+MGLPrivateAdditions.h
+++ b/platform/darwin/src/NSExpression+MGLPrivateAdditions.h
@@ -27,6 +27,11 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) mbgl::FeatureIdentifier mgl_featureIdentifier;
@property (nonatomic, readonly) std::vector<mbgl::FeatureIdentifier> mgl_aggregateFeatureIdentifier;
+/**
+ Returns a copy of the receiver with tokens replaced by key path expressions.
+ */
+- (NSExpression *)mgl_expressionByReplacingTokensWithKeyPaths;
+
@end
@interface NSNull (MGLExpressionAdditions)
@@ -60,6 +65,8 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, readonly) id mgl_jsonExpressionObject;
+- (id)mgl_has:(id)element;
+
@end
@interface MGLColor (MGLExpressionAdditions)
@@ -72,6 +79,9 @@ NS_ASSUME_NONNULL_BEGIN
- (NSExpression *)mgl_expressionWithContext:(NSDictionary<NSString *, NSExpression *> *)context;
+
+- (id)mgl_has:(id)element;
+
@end
extern NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects);
diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.h b/platform/darwin/src/NSPredicate+MGLAdditions.h
index 89e9e65c64..a73b1a61ba 100644
--- a/platform/darwin/src/NSPredicate+MGLAdditions.h
+++ b/platform/darwin/src/NSPredicate+MGLAdditions.h
@@ -16,4 +16,8 @@
@property (nonatomic, readonly) id mgl_jsonExpressionObject;
+- (id)mgl_if:(id)firstValue, ...;
+
+- (id)mgl_match:(NSExpression *)firstCase, ...;
+
@end
diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.mm b/platform/darwin/src/NSPredicate+MGLAdditions.mm
index 63c8307803..bbd324bb63 100644
--- a/platform/darwin/src/NSPredicate+MGLAdditions.mm
+++ b/platform/darwin/src/NSPredicate+MGLAdditions.mm
@@ -3,6 +3,8 @@
#import "MGLValueEvaluator.h"
#import "MGLStyleValue_Private.h"
+#include <mbgl/style/conversion/filter.hpp>
+
class FilterEvaluator {
public:
@@ -206,25 +208,18 @@ public:
- (mbgl::style::Filter)mgl_filter
{
- if ([self isEqual:[NSPredicate predicateWithValue:YES]])
- {
- return mbgl::style::AllFilter();
- }
-
- if ([self isEqual:[NSPredicate predicateWithValue:NO]])
- {
- return mbgl::style::AnyFilter();
- }
-
- if ([self.predicateFormat hasPrefix:@"BLOCKPREDICATE("])
- {
+ mbgl::style::conversion::Error valueError;
+ NSArray *jsonObject = self.mgl_jsonExpressionObject;
+ auto value = mbgl::style::conversion::convert<mbgl::style::Filter>(mbgl::style::conversion::makeConvertible(jsonObject), valueError);
+
+ if (!value) {
[NSException raise:NSInvalidArgumentException
- format:@"Block-based predicates are not supported."];
+ format:@"Invalid filter value: %@", @(valueError.message.c_str())];
+ return {};
}
-
- [NSException raise:NSInvalidArgumentException
- format:@"Unrecognized predicate type."];
- return {};
+ mbgl::style::Filter filter = std::move(*value);
+
+ return filter;
}
+ (instancetype)mgl_predicateWithFilter:(mbgl::style::Filter)filter
@@ -280,7 +275,7 @@ NSArray *MGLSubpredicatesWithJSONObjects(NSArray *objects) {
}
if ([op isEqualToString:@">="]) {
NSArray *subexpressions = MGLSubexpressionsWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]);
- return [NSPredicate predicateWithFormat:@"%K >= %@" argumentArray:subexpressions];
+ return [NSPredicate predicateWithFormat:@"%@ >= %@" argumentArray:subexpressions];
}
if ([op isEqualToString:@"!"]) {
NSArray *subpredicates = MGLSubpredicatesWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]);
@@ -294,7 +289,43 @@ NSArray *MGLSubpredicatesWithJSONObjects(NSArray *objects) {
return [NSPredicate predicateWithValue:YES];
}
if ([op isEqualToString:@"all"]) {
- NSArray *subpredicates = MGLSubpredicatesWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]);
+ NSArray<NSPredicate *> *subpredicates = MGLSubpredicatesWithJSONObjects([objects subarrayWithRange:NSMakeRange(1, objects.count - 1)]);
+ if (subpredicates.count == 2) {
+ // Determine if the expression is of BETWEEN type
+ if ([subpredicates[0] isKindOfClass:[NSComparisonPredicate class]] &&
+ [subpredicates[1] isKindOfClass:[NSComparisonPredicate class]]) {
+ NSComparisonPredicate *leftCondition = (NSComparisonPredicate *)subpredicates[0];
+ NSComparisonPredicate *rightCondition = (NSComparisonPredicate *)subpredicates[1];
+
+ NSArray *limits;
+ NSExpression *leftConditionExpression;
+
+ if(leftCondition.predicateOperatorType == NSGreaterThanOrEqualToPredicateOperatorType &&
+ rightCondition.predicateOperatorType == NSLessThanOrEqualToPredicateOperatorType) {
+ limits = @[leftCondition.rightExpression, rightCondition.rightExpression];
+ leftConditionExpression = leftCondition.leftExpression;
+
+ } else if (leftCondition.predicateOperatorType == NSLessThanOrEqualToPredicateOperatorType &&
+ rightCondition.predicateOperatorType == NSLessThanOrEqualToPredicateOperatorType) {
+ limits = @[leftCondition.leftExpression, rightCondition.rightExpression];
+ leftConditionExpression = leftCondition.rightExpression;
+
+ } else if(leftCondition.predicateOperatorType == NSLessThanOrEqualToPredicateOperatorType &&
+ rightCondition.predicateOperatorType == NSGreaterThanOrEqualToPredicateOperatorType) {
+ limits = @[leftCondition.leftExpression, rightCondition.leftExpression];
+ leftConditionExpression = leftCondition.rightExpression;
+
+ } else if(leftCondition.predicateOperatorType == NSGreaterThanOrEqualToPredicateOperatorType &&
+ rightCondition.predicateOperatorType == NSGreaterThanOrEqualToPredicateOperatorType) {
+ limits = @[leftCondition.rightExpression, rightCondition.leftExpression];
+ leftConditionExpression = leftCondition.leftExpression;
+ }
+
+ if (limits && leftConditionExpression) {
+ return [NSPredicate predicateWithFormat:@"%@ BETWEEN %@", leftConditionExpression, [NSExpression expressionForAggregate:limits]];
+ }
+ }
+ }
return [NSCompoundPredicate andPredicateWithSubpredicates:subpredicates];
}
if ([op isEqualToString:@"any"]) {
@@ -302,8 +333,13 @@ NSArray *MGLSubpredicatesWithJSONObjects(NSArray *objects) {
return [NSCompoundPredicate orPredicateWithSubpredicates:subpredicates];
}
- NSAssert(NO, @"Unrecognized expression conditional operator %@.", op);
- return nil;
+ NSExpression *expression = [NSExpression expressionWithMGLJSONObject:object];
+ return [NSComparisonPredicate predicateWithLeftExpression:expression
+ rightExpression:[NSExpression expressionForConstantValue:@YES]
+ modifier:NSDirectPredicateModifier
+ type:NSEqualToPredicateOperatorType
+ options:0];
+
}
- (id)mgl_jsonExpressionObject {
@@ -324,4 +360,35 @@ NSArray *MGLSubpredicatesWithJSONObjects(NSArray *objects) {
return nil;
}
+- (id)mgl_if:(id)firstValue, ... {
+
+ if ([self evaluateWithObject:nil]) {
+ return firstValue;
+ }
+
+ id eachExpression;
+ va_list argumentList;
+ va_start(argumentList, firstValue);
+
+ while ((eachExpression = va_arg(argumentList, id))) {
+ if ([eachExpression isKindOfClass:[NSComparisonPredicate class]]) {
+ id valueExpression = va_arg(argumentList, id);
+ if ([eachExpression evaluateWithObject:nil]) {
+ return valueExpression;
+ }
+ } else {
+ return eachExpression;
+ }
+ }
+ va_end(argumentList);
+
+ return nil;
+}
+
+- (id)mgl_match:(NSExpression *)firstCase, ... {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Match expressions lack underlying Objective-C implementations."];
+ return nil;
+}
+
@end
diff --git a/platform/darwin/src/NSString+MGLAdditions.m b/platform/darwin/src/NSString+MGLAdditions.m
index 8c9bbe3e21..a61f229511 100644
--- a/platform/darwin/src/NSString+MGLAdditions.m
+++ b/platform/darwin/src/NSString+MGLAdditions.m
@@ -1,5 +1,9 @@
#import "NSString+MGLAdditions.h"
+#if TARGET_OS_OSX
+ #import <Availability.h>
+#endif
+
@implementation NSString (MGLAdditions)
- (NSRange)mgl_wholeRange {
@@ -13,7 +17,7 @@
- (NSString *)mgl_titleCasedStringWithLocale:(NSLocale *)locale {
NSMutableString *string = self.mutableCopy;
NSOrthography *orthography;
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000
+#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 110000 || __MAC_OS_X_VERSION_MAX_ALLOWED >= 101300
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
if ([NSOrthography respondsToSelector:@selector(defaultOrthographyForLanguage:)]) {
diff --git a/platform/darwin/src/NSValue+MGLAdditions.h b/platform/darwin/src/NSValue+MGLAdditions.h
index f3026a389f..9222f04620 100644
--- a/platform/darwin/src/NSValue+MGLAdditions.h
+++ b/platform/darwin/src/NSValue+MGLAdditions.h
@@ -29,6 +29,19 @@ NS_ASSUME_NONNULL_BEGIN
@property (readonly) CLLocationCoordinate2D MGLCoordinateValue;
/**
+ Creates a new value object containing the specified Mapbox map point structure.
+
+ @param point The value for the new object.
+ @return A new value object that contains the coordinate and zoom level information.
+ */
++ (instancetype)valueWithMGLMapPoint:(MGLMapPoint)point;
+
+/**
+ The Mapbox map point structure representation of the value.
+ */
+@property (readonly) MGLMapPoint MGLMapPointValue;
+
+/**
Creates a new value object containing the specified Mapbox coordinate span
structure.
diff --git a/platform/darwin/src/NSValue+MGLAdditions.m b/platform/darwin/src/NSValue+MGLAdditions.m
index 1383056944..b32445dab7 100644
--- a/platform/darwin/src/NSValue+MGLAdditions.m
+++ b/platform/darwin/src/NSValue+MGLAdditions.m
@@ -14,6 +14,16 @@
return coordinate;
}
++ (instancetype)valueWithMGLMapPoint:(MGLMapPoint)point {
+ return [self valueWithBytes:&point objCType:@encode(MGLMapPoint)];
+}
+
+-(MGLMapPoint) MGLMapPointValue {
+ MGLMapPoint point;
+ [self getValue:&point];
+ return point;
+}
+
+ (instancetype)valueWithMGLCoordinateSpan:(MGLCoordinateSpan)span {
return [self valueWithBytes:&span objCType:@encode(MGLCoordinateSpan)];
}
diff --git a/platform/darwin/test/MGLBackgroundStyleLayerTests.mm b/platform/darwin/test/MGLBackgroundStyleLayerTests.mm
index e7c2982413..de8080f425 100644
--- a/platform/darwin/test/MGLBackgroundStyleLayerTests.mm
+++ b/platform/darwin/test/MGLBackgroundStyleLayerTests.mm
@@ -42,7 +42,7 @@
@"backgroundColor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.backgroundColor = functionExpression;
mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
@@ -66,8 +66,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.backgroundColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLBackgroundLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.backgroundColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLBackgroundLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.backgroundColorTransition = transitionTest;
@@ -95,7 +95,7 @@
@"backgroundOpacity should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.backgroundOpacity = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -119,8 +119,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.backgroundOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLBackgroundLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.backgroundOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLBackgroundLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.backgroundOpacityTransition = transitionTest;
@@ -148,7 +148,7 @@
@"backgroundPattern should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'Background Pattern'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.backgroundPattern = functionExpression;
mbgl::style::IntervalStops<std::string> intervalStops = {{
@@ -172,8 +172,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.backgroundPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLBackgroundLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.backgroundPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLBackgroundLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.backgroundPatternTransition = transitionTest;
diff --git a/platform/darwin/test/MGLCircleStyleLayerTests.mm b/platform/darwin/test/MGLCircleStyleLayerTests.mm
index 7677344580..d7bf2a5afd 100644
--- a/platform/darwin/test/MGLCircleStyleLayerTests.mm
+++ b/platform/darwin/test/MGLCircleStyleLayerTests.mm
@@ -30,8 +30,8 @@
XCTAssertNil(layer.sourceLayerIdentifier);
XCTAssertNil(layer.predicate);
- layer.predicate = [NSPredicate predicateWithValue:NO];
- XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
+ layer.predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"]);
layer.predicate = nil;
XCTAssertNil(layer.predicate);
}
@@ -63,7 +63,7 @@
@"circleBlur should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.circleBlur = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -77,7 +77,7 @@
XCTAssertEqualObjects(layer.circleBlur, functionExpression,
@"circleBlur should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.circleBlur = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -85,10 +85,11 @@
XCTAssertEqual(rawLayer->getCircleBlur(), propertyValue,
@"Setting circleBlur to a data expression should update circle-blur.");
- XCTAssertEqualObjects(layer.circleBlur, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.circleBlur, pedanticFunctionExpression,
@"circleBlur should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.circleBlur = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -98,7 +99,8 @@
XCTAssertEqual(rawLayer->getCircleBlur(), propertyValue,
@"Setting circleBlur to a camera-data expression should update circle-blur.");
- XCTAssertEqualObjects(layer.circleBlur, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleBlur, pedanticFunctionExpression,
@"circleBlur should round-trip camera-data expressions.");
@@ -133,7 +135,7 @@
@"circleColor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.circleColor = functionExpression;
mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
@@ -147,7 +149,7 @@
XCTAssertEqualObjects(layer.circleColor, functionExpression,
@"circleColor should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.circleColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
@@ -155,10 +157,11 @@
XCTAssertEqual(rawLayer->getCircleColor(), propertyValue,
@"Setting circleColor to a data expression should update circle-color.");
- XCTAssertEqualObjects(layer.circleColor, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.circleColor, pedanticFunctionExpression,
@"circleColor should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.circleColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
@@ -168,7 +171,8 @@
XCTAssertEqual(rawLayer->getCircleColor(), propertyValue,
@"Setting circleColor to a camera-data expression should update circle-color.");
- XCTAssertEqualObjects(layer.circleColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleColor, pedanticFunctionExpression,
@"circleColor should round-trip camera-data expressions.");
@@ -203,7 +207,7 @@
@"circleOpacity should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.circleOpacity = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -217,7 +221,7 @@
XCTAssertEqualObjects(layer.circleOpacity, functionExpression,
@"circleOpacity should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.circleOpacity = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -225,10 +229,11 @@
XCTAssertEqual(rawLayer->getCircleOpacity(), propertyValue,
@"Setting circleOpacity to a data expression should update circle-opacity.");
- XCTAssertEqualObjects(layer.circleOpacity, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.circleOpacity, pedanticFunctionExpression,
@"circleOpacity should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.circleOpacity = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -238,7 +243,8 @@
XCTAssertEqual(rawLayer->getCircleOpacity(), propertyValue,
@"Setting circleOpacity to a camera-data expression should update circle-opacity.");
- XCTAssertEqualObjects(layer.circleOpacity, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleOpacity, pedanticFunctionExpression,
@"circleOpacity should round-trip camera-data expressions.");
@@ -273,7 +279,7 @@
@"circlePitchAlignment should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.circlePitchAlignment = functionExpression;
mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = {{
@@ -297,8 +303,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.circlePitchAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.circlePitchAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -317,7 +323,7 @@
@"circleRadius should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.circleRadius = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -331,7 +337,7 @@
XCTAssertEqualObjects(layer.circleRadius, functionExpression,
@"circleRadius should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.circleRadius = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -339,10 +345,11 @@
XCTAssertEqual(rawLayer->getCircleRadius(), propertyValue,
@"Setting circleRadius to a data expression should update circle-radius.");
- XCTAssertEqualObjects(layer.circleRadius, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.circleRadius, pedanticFunctionExpression,
@"circleRadius should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.circleRadius = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -352,7 +359,8 @@
XCTAssertEqual(rawLayer->getCircleRadius(), propertyValue,
@"Setting circleRadius to a camera-data expression should update circle-radius.");
- XCTAssertEqualObjects(layer.circleRadius, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleRadius, pedanticFunctionExpression,
@"circleRadius should round-trip camera-data expressions.");
@@ -387,7 +395,7 @@
@"circleScaleAlignment should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.circleScaleAlignment = functionExpression;
mbgl::style::IntervalStops<mbgl::style::CirclePitchScaleType> intervalStops = {{
@@ -411,8 +419,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.circleScaleAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.circleScaleAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -431,7 +439,7 @@
@"circleStrokeColor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.circleStrokeColor = functionExpression;
mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
@@ -445,7 +453,7 @@
XCTAssertEqualObjects(layer.circleStrokeColor, functionExpression,
@"circleStrokeColor should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.circleStrokeColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
@@ -453,10 +461,11 @@
XCTAssertEqual(rawLayer->getCircleStrokeColor(), propertyValue,
@"Setting circleStrokeColor to a data expression should update circle-stroke-color.");
- XCTAssertEqualObjects(layer.circleStrokeColor, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeColor, pedanticFunctionExpression,
@"circleStrokeColor should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.circleStrokeColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
@@ -466,7 +475,8 @@
XCTAssertEqual(rawLayer->getCircleStrokeColor(), propertyValue,
@"Setting circleStrokeColor to a camera-data expression should update circle-stroke-color.");
- XCTAssertEqualObjects(layer.circleStrokeColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeColor, pedanticFunctionExpression,
@"circleStrokeColor should round-trip camera-data expressions.");
@@ -501,7 +511,7 @@
@"circleStrokeOpacity should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.circleStrokeOpacity = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -515,7 +525,7 @@
XCTAssertEqualObjects(layer.circleStrokeOpacity, functionExpression,
@"circleStrokeOpacity should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.circleStrokeOpacity = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -523,10 +533,11 @@
XCTAssertEqual(rawLayer->getCircleStrokeOpacity(), propertyValue,
@"Setting circleStrokeOpacity to a data expression should update circle-stroke-opacity.");
- XCTAssertEqualObjects(layer.circleStrokeOpacity, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, pedanticFunctionExpression,
@"circleStrokeOpacity should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.circleStrokeOpacity = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -536,7 +547,8 @@
XCTAssertEqual(rawLayer->getCircleStrokeOpacity(), propertyValue,
@"Setting circleStrokeOpacity to a camera-data expression should update circle-stroke-opacity.");
- XCTAssertEqualObjects(layer.circleStrokeOpacity, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeOpacity, pedanticFunctionExpression,
@"circleStrokeOpacity should round-trip camera-data expressions.");
@@ -571,7 +583,7 @@
@"circleStrokeWidth should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.circleStrokeWidth = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -585,7 +597,7 @@
XCTAssertEqualObjects(layer.circleStrokeWidth, functionExpression,
@"circleStrokeWidth should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.circleStrokeWidth = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -593,10 +605,11 @@
XCTAssertEqual(rawLayer->getCircleStrokeWidth(), propertyValue,
@"Setting circleStrokeWidth to a data expression should update circle-stroke-width.");
- XCTAssertEqualObjects(layer.circleStrokeWidth, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeWidth, pedanticFunctionExpression,
@"circleStrokeWidth should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.circleStrokeWidth = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -606,7 +619,8 @@
XCTAssertEqual(rawLayer->getCircleStrokeWidth(), propertyValue,
@"Setting circleStrokeWidth to a camera-data expression should update circle-stroke-width.");
- XCTAssertEqualObjects(layer.circleStrokeWidth, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.circleStrokeWidth, pedanticFunctionExpression,
@"circleStrokeWidth should round-trip camera-data expressions.");
@@ -647,7 +661,7 @@
@"circleTranslation should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.circleTranslation = functionExpression;
mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
@@ -671,8 +685,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.circleTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.circleTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -691,7 +705,7 @@
@"circleTranslationAnchor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.circleTranslationAnchor = functionExpression;
mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = {{
@@ -715,8 +729,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.circleTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.circleTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLCircleLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
}
diff --git a/platform/darwin/test/MGLDocumentationExampleTests.swift b/platform/darwin/test/MGLDocumentationExampleTests.swift
index a216d9ad1c..9edb33a078 100644
--- a/platform/darwin/test/MGLDocumentationExampleTests.swift
+++ b/platform/darwin/test/MGLDocumentationExampleTests.swift
@@ -73,14 +73,14 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
XCTAssertNotNil(mapView.style?.source(withIdentifier: "lines"))
}
- func testMGLRasterSource() {
+ func testMGLRasterTileSource() {
//#-example-code
- let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [
+ let source = MGLRasterTileSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [
.minimumZoomLevel: 9,
.maximumZoomLevel: 16,
.tileSize: 512,
.attributionInfos: [
- MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com"))
+ MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "https://mapbox.com"))
]
])
mapView.style?.addSource(source)
@@ -109,13 +109,13 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
XCTAssertNotNil(mapView.style?.source(withIdentifier: "hills"))
}
- func testMGLVectorSource() {
+ func testMGLVectorTileSource() {
//#-example-code
- let source = MGLVectorSource(identifier: "pois", tileURLTemplates: ["https://example.com/vector-tiles/{z}/{x}/{y}.mvt"], options: [
+ let source = MGLVectorTileSource(identifier: "pois", tileURLTemplates: ["https://example.com/vector-tiles/{z}/{x}/{y}.mvt"], options: [
.minimumZoomLevel: 9,
.maximumZoomLevel: 16,
.attributionInfos: [
- MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com"))
+ MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "https://mapbox.com"))
]
])
mapView.style?.addSource(source)
@@ -151,7 +151,7 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
}
func testMGLCircleStyleLayer() {
- let population = MGLVectorSource(identifier: "population", configurationURL: URL(string: "https://example.com/style.json")!)
+ let population = MGLVectorTileSource(identifier: "population", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style?.addSource(population)
//#-example-code
@@ -162,7 +162,7 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
#else
layer.circleColor = NSExpression(forConstantValue: UIColor.green)
#endif
- layer.circleRadius = NSExpression(format: "FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'exponential', 1.75, %@)",
+ layer.circleRadius = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'exponential', 1.75, %@)",
[12: 2,
22: 180])
layer.circleOpacity = NSExpression(forConstantValue: 0.7)
@@ -174,13 +174,13 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
}
func testMGLLineStyleLayer() {
- let trails = MGLVectorSource(identifier: "trails", configurationURL: URL(string: "https://example.com/style.json")!)
+ let trails = MGLVectorTileSource(identifier: "trails", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style?.addSource(trails)
//#-example-code
let layer = MGLLineStyleLayer(identifier: "trails-path", source: trails)
layer.sourceLayerIdentifier = "trails"
- layer.lineWidth = NSExpression(format: "FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'exponential', 1.5, %@)",
+ layer.lineWidth = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'exponential', 1.5, %@)",
[14: 2,
18: 20])
#if os(macOS)
@@ -197,7 +197,7 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
}
func testMGLFillStyleLayer() {
- let parks = MGLVectorSource(identifier: "parks", configurationURL: URL(string: "https://example.com/style.json")!)
+ let parks = MGLVectorTileSource(identifier: "parks", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style?.addSource(parks)
//#-example-code
@@ -216,7 +216,7 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
}
func testMGLFillExtrusionStyleLayer() {
- let buildings = MGLVectorSource(identifier: "buildings", configurationURL: URL(string: "https://example.com/style.json")!)
+ let buildings = MGLVectorTileSource(identifier: "buildings", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style?.addSource(buildings)
//#-example-code
@@ -237,10 +237,10 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
//#-example-code
let layer = MGLHeatmapStyleLayer(identifier: "earthquake-heat", source: earthquakes)
- layer.heatmapWeight = NSExpression(format: "FUNCTION(magnitude, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
+ layer.heatmapWeight = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:(magnitude, 'linear', nil, %@)",
[0: 0,
6: 1])
- layer.heatmapIntensity = NSExpression(format: "FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
+ layer.heatmapIntensity = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)",
[0: 1,
9: 3])
mapView.style?.addLayer(layer)
@@ -250,7 +250,7 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
}
func testMGLSymbolStyleLayer() {
- let pois = MGLVectorSource(identifier: "pois", configurationURL: URL(string: "https://example.com/style.json")!)
+ let pois = MGLVectorTileSource(identifier: "pois", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style?.addSource(pois)
//#-example-code
@@ -275,12 +275,12 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
}
func testMGLRasterStyleLayer() {
- let source = MGLRasterSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [
+ let source = MGLRasterTileSource(identifier: "clouds", tileURLTemplates: ["https://example.com/raster-tiles/{z}/{x}/{y}.png"], options: [
.minimumZoomLevel: 9,
.maximumZoomLevel: 16,
.tileSize: 512,
.attributionInfos: [
- MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com"))
+ MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "https://mapbox.com"))
]
])
mapView.style?.addSource(source)
@@ -300,12 +300,12 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
.maximumZoomLevel: 16,
.tileSize: 256,
.attributionInfos: [
- MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "http://mapbox.com"))
+ MGLAttributionInfo(title: NSAttributedString(string: "© Mapbox"), url: URL(string: "https://mapbox.com"))
]
])
mapView.style?.addSource(source)
- let canals = MGLVectorSource(identifier: "canals", configurationURL: URL(string: "https://example.com/style.json")!)
+ let canals = MGLVectorTileSource(identifier: "canals", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style?.addSource(canals)
let canalShadowLayer = MGLLineStyleLayer(identifier: "waterway-river-canal-shadow", source: canals)
mapView.style?.addLayer(canalShadowLayer)
@@ -322,13 +322,13 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
}
func testMGLVectorStyleLayer$predicate() {
- let terrain = MGLVectorSource(identifier: "terrain", configurationURL: URL(string: "https://example.com/style.json")!)
+ let terrain = MGLVectorTileSource(identifier: "terrain", configurationURL: URL(string: "https://example.com/style.json")!)
mapView.style?.addSource(terrain)
//#-example-code
let layer = MGLLineStyleLayer(identifier: "contour", source: terrain)
layer.sourceLayerIdentifier = "contours"
- layer.predicate = NSPredicate(format: "(index == 5 || index == 10) && ele >= 1500.0")
+ layer.predicate = NSPredicate(format: "(index == 5 || index == 10) && CAST(ele, 'NSNumber') >= 1500.0")
mapView.style?.addLayer(layer)
//#-end-example-code
@@ -370,7 +370,7 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
#endif
class MGLStyle {
- static func satelliteStreetsStyleURL() -> URL {
+ static var satelliteStreetsStyleURL: URL {
return MGLDocumentationExampleTests.styleURL
}
}
@@ -378,7 +378,7 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
//#-example-code
let camera = MGLMapCamera(lookingAtCenter: CLLocationCoordinate2D(latitude: 37.7184, longitude: -122.4365), fromDistance: 100, pitch: 20, heading: 0)
- let options = MGLMapSnapshotOptions(styleURL: MGLStyle.satelliteStreetsStyleURL(), camera: camera, size: CGSize(width: 320, height: 480))
+ let options = MGLMapSnapshotOptions(styleURL: MGLStyle.satelliteStreetsStyleURL, camera: camera, size: CGSize(width: 320, height: 480))
options.zoomLevel = 10
let snapshotter = MGLMapSnapshotter(options: options)
diff --git a/platform/darwin/test/MGLDocumentationGuideTests.swift b/platform/darwin/test/MGLDocumentationGuideTests.swift
index f939695f32..4de1d81aa9 100644
--- a/platform/darwin/test/MGLDocumentationGuideTests.swift
+++ b/platform/darwin/test/MGLDocumentationGuideTests.swift
@@ -50,10 +50,10 @@ class MGLDocumentationGuideTests: XCTestCase, MGLMapViewDelegate {
styleLoadingExpectation.fulfill()
}
- func testUsingStyleFunctionsAtRuntime$Stops() {
+ func testMigratingToExpressions$Stops() {
//#-example-code
#if os(macOS)
- let stops: [Float: NSColor] = [
+ let stops: [NSNumber: NSColor] = [
0: .yellow,
2.5: .orange,
5: .red,
@@ -61,7 +61,7 @@ class MGLDocumentationGuideTests: XCTestCase, MGLMapViewDelegate {
10: .white,
]
#else
- let stops: [Float: UIColor] = [
+ let stops: [NSNumber: UIColor] = [
0: .yellow,
2.5: .orange,
5: .red,
@@ -71,11 +71,11 @@ class MGLDocumentationGuideTests: XCTestCase, MGLMapViewDelegate {
#endif
//#-end-example-code
- let _ = NSExpression(format: "FUNCTION(mag, 'mgl_stepWithMinimum:stops:', %@, %@)",
+ let _ = NSExpression(format: "mgl_step:from:stops:(mag, %@, %@)",
stops[0]!, stops)
}
- func testUsingStyleFunctionsAtRuntime$Linear() {
+ func testMigratingToExpressions$Linear() {
//#-example-code
let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
let symbolSource = MGLSource(identifier: "source")
@@ -85,7 +85,7 @@ class MGLDocumentationGuideTests: XCTestCase, MGLMapViewDelegate {
mapView.style?.addSource(source)
#if os(macOS)
- let stops: [Float: NSColor] = [
+ let stops: [NSNumber: NSColor] = [
0: .yellow,
2.5: .orange,
5: .red,
@@ -93,7 +93,7 @@ class MGLDocumentationGuideTests: XCTestCase, MGLMapViewDelegate {
10: .white,
]
#else
- let stops: [Float: UIColor] = [
+ let stops: [NSNumber: UIColor] = [
0: .yellow,
2.5: .orange,
5: .red,
@@ -104,10 +104,10 @@ class MGLDocumentationGuideTests: XCTestCase, MGLMapViewDelegate {
let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
#if os(macOS)
- layer.circleColor = NSExpression(format: "FUNCTION(mag, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
+ layer.circleColor = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:(mag, 'linear', nil, %@)",
stops)
#else
- layer.circleColor = NSExpression(format: "FUNCTION(mag, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
+ layer.circleColor = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:(mag, 'linear', nil, %@)",
stops)
#endif
layer.circleRadius = NSExpression(forConstantValue: 10)
@@ -115,7 +115,37 @@ class MGLDocumentationGuideTests: XCTestCase, MGLMapViewDelegate {
//#-end-example-code
}
- func testUsingStyleFunctionsAtRuntime$Exponential() {
+ func testMigratingToExpressions$LinearConvenience() {
+ let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
+ let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
+
+ #if os(macOS)
+ let stops: [NSNumber: NSColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
+ ]
+ #else
+ let stops: [NSNumber: UIColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
+ ]
+ #endif
+
+ //#-example-code
+ layer.circleColor = NSExpression(forMGLInterpolating: NSExpression(forKeyPath: "mag"), curveType: .linear, parameters: nil, stops: NSExpression(forConstantValue: stops))
+ //#-end-example-code
+
+ layer.circleRadius = NSExpression(forConstantValue: 10)
+ mapView.style?.addLayer(layer)
+
+ }
+ func testMigratingToExpressions$Exponential() {
let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
@@ -126,18 +156,32 @@ class MGLDocumentationGuideTests: XCTestCase, MGLMapViewDelegate {
18: 18,
]
- layer.circleRadius = NSExpression(format: "FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'exponential', 1.5, %@)",
+ layer.circleRadius = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'exponential', 1.5, %@)",
stops)
//#-end-example-code
}
- func testUsingStyleFunctionsAtRuntime$Interval() {
+ func testMigratingToExpressions$ExponentialConvenience() {
+ let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
+ let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
+
+ //#-example-code
+ let stops = [
+ 12: 0.5,
+ 14: 2,
+ 18: 18,
+ ]
+
+ layer.circleRadius = NSExpression(forMGLInterpolating: NSExpression.zoomLevelVariable, curveType: MGLExpressionInterpolationMode.exponential, parameters: NSExpression(forConstantValue: 1.5), stops: NSExpression(forConstantValue: stops))
+ //#-end-example-code
+ }
+ func testMigratingToExpressions$Interval() {
let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
//#-example-code
#if os(macOS)
- let stops: [Float: NSColor] = [
+ let stops: [NSNumber: NSColor] = [
0: .yellow,
2.5: .orange,
5: .red,
@@ -145,10 +189,10 @@ class MGLDocumentationGuideTests: XCTestCase, MGLMapViewDelegate {
10: .white,
]
- layer.circleColor = NSExpression(format: "FUNCTION(mag, 'mgl_stepWithMinimum:stops:', %@, %@)",
+ layer.circleColor = NSExpression(format: "mgl_step:from:stops:(mag, %@, %@)",
NSColor.green, stops)
#else
- let stops: [Float: UIColor] = [
+ let stops: [NSNumber: UIColor] = [
0: .yellow,
2.5: .orange,
5: .red,
@@ -156,40 +200,53 @@ class MGLDocumentationGuideTests: XCTestCase, MGLMapViewDelegate {
10: .white,
]
- layer.circleColor = NSExpression(format: "FUNCTION(mag, 'mgl_stepWithMinimum:stops:', %@, %@)",
+ layer.circleColor = NSExpression(format: "mgl_step:from:stops:(mag, %@, %@)",
UIColor.green, stops)
#endif
//#-end-example-code
}
- func testUsingStyleFunctionsAtRuntime$Categorical() {
+ func testMigratingToExpressions$Categorical() {
let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
//#-example-code
#if os(macOS)
- let colors: [String: NSColor] = [
- "earthquake": .orange,
- "explosion": .red,
- "quarry blast": .yellow,
- ]
let defaultColor = NSColor.blue
+ layer.circleColor = NSExpression(
+ format: "MGL_MATCH(type, 'earthquake', %@, 'explosion', %@, 'quarry blast', %@, %@)",
+ NSColor.orange, NSColor.red, NSColor.yellow, defaultColor)
#else
- let colors: [String: UIColor] = [
- "earthquake": .orange,
- "explosion": .red,
- "quarry blast": .yellow,
- ]
let defaultColor = UIColor.blue
+ layer.circleColor = NSExpression(format: "MGL_MATCH(type, 'earthquake', %@, 'explosion', %@, 'quarry blast', %@, %@)",
+ UIColor.orange, UIColor.red, UIColor.yellow, defaultColor)
#endif
+ //#-end-example-code
+ }
+
+ func testMigratingToExpressions$CategoricalValue() {
+ let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
+ let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
+ //#-example-code
+ #if os(macOS)
+ let stops : [String : NSColor] = ["earthquake" : NSColor.orange,
+ "explosion" : NSColor.red,
+ "quarry blast" : NSColor.yellow]
+ layer.circleColor = NSExpression(
+ format: "FUNCTION(%@, 'valueForKeyPath:', type)",
+ stops)
+ #else
+ let stops : [String : UIColor] = ["earthquake" : UIColor.orange,
+ "explosion" : UIColor.red,
+ "quarry blast" : UIColor.yellow]
layer.circleColor = NSExpression(
- format: "TERNARY(FUNCTION(%@, 'valueForKeyPath:', type) != nil, FUNCTION(%@, 'valueForKeyPath:', type), %@)",
- colors, colors, defaultColor)
+ format: "FUNCTION(%@, 'valueForKeyPath:', type)",
+ stops)
+ #endif
//#-end-example-code
}
-
- func testUsingStyleFunctionsAtRuntime$Identity() {
+ func testMigratingToExpressions$Identity() {
let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
@@ -197,4 +254,23 @@ class MGLDocumentationGuideTests: XCTestCase, MGLMapViewDelegate {
layer.circleRadius = NSExpression(forKeyPath: "mag")
//#-end-example-code
}
+
+ func testMigratingToExpressions$Multiply() {
+ let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
+ let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
+
+ //#-example-code
+ layer.circleRadius = NSExpression(forFunction: "multiply:by:", arguments: [NSExpression(forKeyPath: "mag"), 3])
+ //#-end-example-code
+ }
+
+ func testMigratingToExpressions$Cast() {
+ let source = MGLShapeSource(identifier: "circles", shape: nil, options: nil)
+
+ //#-example-code
+ let magnitudeLayer = MGLSymbolStyleLayer(identifier: "mag-layer", source: source)
+ magnitudeLayer.text = NSExpression(format: "CAST(mag, 'NSString')")
+ mapView.style?.addLayer(magnitudeLayer)
+ //#-end-example-code
+ }
}
diff --git a/platform/darwin/test/MGLExpressionTests.mm b/platform/darwin/test/MGLExpressionTests.mm
index a5ed2f7bf5..d54e961b00 100644
--- a/platform/darwin/test/MGLExpressionTests.mm
+++ b/platform/darwin/test/MGLExpressionTests.mm
@@ -158,7 +158,7 @@ using namespace std::string_literals;
NSExpression *expression = [NSExpression expressionForVariable:@"zoomLevel"];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @[@"zoom"]);
XCTAssertEqualObjects([NSExpression expressionWithFormat:@"$zoomLevel"].mgl_jsonExpressionObject, @[@"zoom"]);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:@[@"zoom"]], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:@[@"zoom"]], expression);
NSMutableDictionary *context = [@{@"zoomLevel": @16} mutableCopy];
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:context], @16);
}
@@ -166,25 +166,45 @@ using namespace std::string_literals;
NSExpression *expression = [NSExpression expressionForVariable:@"heatmapDensity"];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @[@"heatmap-density"]);
XCTAssertEqualObjects([NSExpression expressionWithFormat:@"$heatmapDensity"].mgl_jsonExpressionObject, @[@"heatmap-density"]);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:@[@"heatmap-density"]], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:@[@"heatmap-density"]], expression);
NSMutableDictionary *context = [@{@"heatmapDensity": @1} mutableCopy];
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:context], @1);
}
{
+ NSExpression *expression = [NSExpression expressionForVariable:@"geometryType"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @[@"geometry-type"]);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"$geometryType"].mgl_jsonExpressionObject, @[@"geometry-type"]);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:@[@"geometry-type"]], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForVariable:@"featureIdentifier"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @[@"id"]);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"$featureIdentifier"].mgl_jsonExpressionObject, @[@"id"]);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:@[@"id"]], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForVariable:@"featureAttributes"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @[@"properties"]);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"$featureAttributes"].mgl_jsonExpressionObject, @[@"properties"]);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:@[@"properties"]], expression);
+ }
+ {
NSExpression *expression = [NSExpression expressionForVariable:@"loremIpsum"];
NSArray *jsonExpression = @[@"var", @"loremIpsum"];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([NSExpression expressionWithFormat:@"$loremIpsum"].mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
NSMutableDictionary *context = [@{@"loremIpsum": @"Lorem ipsum dolor sit amet"} mutableCopy];
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:context], @"Lorem ipsum dolor sit amet");
}
{
NSDictionary *context = @{@"loremIpsum": MGLConstantExpression(@"Lorem ipsum dolor sit amet")};
- NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(uppercase($loremIpsum), 'mgl_expressionWithContext:', %@)", context];
+ NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_LET('loremIpsum', 'Lorem ipsum dolor sit amet', uppercase($loremIpsum))", context];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(uppercase($loremIpsum), 'mgl_expressionWithContext:', %@)", context];
NSArray *jsonExpression = @[@"let", @"loremIpsum", @"Lorem ipsum dolor sit amet", @[@"upcase", @[@"var", @"loremIpsum"]]];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
}
@@ -193,28 +213,28 @@ using namespace std::string_literals;
NSExpression *expression = [NSExpression expressionForConstantValue:nil];
XCTAssert(expression.mgl_jsonExpressionObject == [NSNull null]);
XCTAssert([NSExpression expressionWithFormat:@"nil"].mgl_jsonExpressionObject == [NSNull null]);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:[NSNull null]], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:[NSNull null]], expression);
XCTAssertNil([expression expressionValueWithObject:nil context:nil]);
}
{
NSExpression *expression = [NSExpression expressionForConstantValue:@1];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @1);
XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1"].mgl_jsonExpressionObject, @1);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:@1], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:@1], expression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @1);
}
{
NSExpression *expression = [NSExpression expressionForConstantValue:@YES];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, @YES);
XCTAssertEqualObjects([NSExpression expressionWithFormat:@"TRUE"].mgl_jsonExpressionObject, @YES);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:@YES], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:@YES], expression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @YES);
}
{
NSExpression *expression = [NSExpression expressionForConstantValue:nil];
XCTAssert(expression.mgl_jsonExpressionObject == [NSNull null]);
XCTAssert([NSExpression expressionWithFormat:@"nil"].mgl_jsonExpressionObject == [NSNull null]);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:[NSNull null]], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:[NSNull null]], expression);
XCTAssertNil([expression expressionValueWithObject:nil context:nil]);
}
{
@@ -227,7 +247,7 @@ using namespace std::string_literals;
#endif
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
// No way to distinguish offsets from ordinary arrays in expressions.
- XCTAssertEqualObjects([[NSExpression mgl_expressionWithJSONObject:jsonExpression].collection valueForKeyPath:@"constantValue"], jsonExpression.lastObject);
+ XCTAssertEqualObjects([[NSExpression expressionWithMGLJSONObject:jsonExpression].collection valueForKeyPath:@"constantValue"], jsonExpression.lastObject);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @(vector));
}
{
@@ -242,7 +262,7 @@ using namespace std::string_literals;
NSArray *jsonExpression = @[@"literal", @[@1, @4, @3, @2]];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
// No way to distinguish offsets from ordinary arrays in expressions.
- XCTAssertEqualObjects([[NSExpression mgl_expressionWithJSONObject:jsonExpression].collection valueForKeyPath:@"constantValue"], jsonExpression.lastObject);
+ XCTAssertEqualObjects([[NSExpression expressionWithMGLJSONObject:jsonExpression].collection valueForKeyPath:@"constantValue"], jsonExpression.lastObject);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], value);
}
{
@@ -272,19 +292,19 @@ using namespace std::string_literals;
NSArray *jsonExpression = @[@"get", @"highway"];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([NSExpression expressionWithFormat:@"highway"].mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionWithFormat:@"%@.population", @{@"population": MGLConstantExpression(@12000)}];
NSArray *jsonExpression = @[@"get", @"population", @[@"literal", @{@"population": @12000}]];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionWithFormat:@"%@.uppercase('population')", @{@"POPULATION": MGLConstantExpression(@12000)}];
NSArray *jsonExpression = @[@"get", @[@"upcase", @"population"], @[@"literal", @{@"POPULATION": @12000}]];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
}
@@ -300,28 +320,28 @@ using namespace std::string_literals;
NSArray *jsonExpression = @[@"+", @1, @2, @2, @3, @4, @7, @9];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @28);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionWithFormat:@"count({1, 2, 2, 3, 4, 7, 9})"];
NSArray *jsonExpression = @[@"length", @[@"literal", @[@1, @2, @2, @3, @4, @7, @9]]];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @7);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionWithFormat:@"min({1, 2, 2, 3, 4, 7, 9})"];
NSArray *jsonExpression = @[@"min", @1, @2, @2, @3, @4, @7, @9];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @1);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionWithFormat:@"max({1, 2, 2, 3, 4, 7, 9})"];
NSArray *jsonExpression = @[@"max", @1, @2, @2, @3, @4, @7, @9];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @9);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
}
@@ -332,61 +352,66 @@ using namespace std::string_literals;
NSArray *jsonExpression = @[@"+", @1, @1];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1 + 1"].mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSArray *arguments = @[MGLConstantExpression(@1), MGLConstantExpression(@1), MGLConstantExpression(@1)];
+ NSExpression *expression = [NSExpression expressionForFunction:@"add:to:" arguments:arguments];
+ NSArray *jsonExpression = @[@"+", @1, @1, @1];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ jsonExpression = @[@"+", @[@"+", @1, @1], @1];
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1 + 1 + 1"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], [NSExpression expressionWithFormat:@"1 + 1 + 1"]);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"from:subtract:" arguments:arguments];
NSArray *jsonExpression = @[@"-", @1, @1];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1 - 1"].mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"multiply:by:" arguments:arguments];
NSArray *jsonExpression = @[@"*", @1, @1];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1 * 1"].mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"divide:by:" arguments:arguments];
NSArray *jsonExpression = @[@"/", @1, @1];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1 / 1"].mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"modulus:by:" arguments:arguments];
NSArray *jsonExpression = @[@"%", @1, @1];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
// NSExpression lacks a shorthand operator for modulus.
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"ceiling:" arguments:@[MGLConstantExpression(@1.5)]];
- NSArray *jsonTruncation = @[@"-", @1.5, @[@"%", @1.5, @1]];
- NSArray *jsonExpression = @[@"+", jsonTruncation, @[@"case", @[@">", @[@"%", @1.5, @1], @0], @1, @0]];
+ NSArray *jsonExpression = @[@"ceil", @1.5];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"ceiling:" arguments:@[MGLConstantExpression(@-1.5)]];
- NSArray *jsonTruncation = @[@"-", @-1.5, @[@"%", @-1.5, @1]];
- NSArray *jsonExpression = @[@"+", jsonTruncation, @[@"case", @[@">", @[@"%", @-1.5, @1], @0], @1, @0]];
+ NSArray *jsonExpression = @[@"ceil", @-1.5];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-1);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"ceiling:" arguments:@[MGLConstantExpression(@2)]];
- NSArray *jsonTruncation = @[@"-", @2, @[@"%", @2, @1]];
- NSArray *jsonExpression = @[@"+", jsonTruncation, @[@"case", @[@">", @[@"%", @2, @1], @0], @1, @0]];
+ NSArray *jsonExpression = @[@"ceil", @2];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"ceiling:" arguments:@[MGLConstantExpression(@-2)]];
- NSArray *jsonTruncation = @[@"-", @-2, @[@"%", @-2, @1]];
- NSArray *jsonExpression = @[@"+", jsonTruncation, @[@"case", @[@">", @[@"%", @-2, @1], @0], @1, @0]];
+ NSArray *jsonExpression = @[@"ceil", @-2];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-2);
}
@@ -404,44 +429,64 @@ using namespace std::string_literals;
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"abs:" arguments:@[MGLConstantExpression(@2)]];
- NSArray *jsonExpression = @[@"*", @2, @[@"case", @[@">", @2, @0], @1, @-1]];
+ NSArray *jsonExpression = @[@"abs", @2];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"abs:" arguments:@[MGLConstantExpression(@-2)]];
- NSArray *jsonExpression = @[@"*", @-2, @[@"case", @[@">", @-2, @0], @1, @-1]];
+ NSArray *jsonExpression = @[@"abs", @-2];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"floor:" arguments:@[MGLConstantExpression(@1.5)]];
- NSArray *jsonTruncation = @[@"-", @1.5, @[@"%", @1.5, @1]];
- NSArray *jsonExpression = @[@"-", jsonTruncation, @[@"case", @[@"<", @[@"%", @1.5, @1], @0], @1, @0]];
+ NSArray *jsonExpression = @[@"floor", @1.5];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @1);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"floor:" arguments:@[MGLConstantExpression(@-1.5)]];
- NSArray *jsonTruncation = @[@"-", @-1.5, @[@"%", @-1.5, @1]];
- NSArray *jsonExpression = @[@"-", jsonTruncation, @[@"case", @[@"<", @[@"%", @-1.5, @1], @0], @1, @0]];
+ NSArray *jsonExpression = @[@"floor", @-1.5];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-2);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"floor:" arguments:@[MGLConstantExpression(@2)]];
- NSArray *jsonTruncation = @[@"-", @2, @[@"%", @2, @1]];
- NSArray *jsonExpression = @[@"-", jsonTruncation, @[@"case", @[@"<", @[@"%", @2, @1], @0], @1, @0]];
+ NSArray *jsonExpression = @[@"floor", @2];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"floor:" arguments:@[MGLConstantExpression(@-2)]];
- NSArray *jsonTruncation = @[@"-", @-2, @[@"%", @-2, @1]];
- NSArray *jsonExpression = @[@"-", jsonTruncation, @[@"case", @[@"<", @[@"%", @-2, @1], @0], @1, @0]];
+ NSArray *jsonExpression = @[@"floor", @-2];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-2);
}
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_round:" arguments:@[MGLConstantExpression(@1.5)]];
+ NSArray *jsonExpression = @[@"round", @1.5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @2);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_round:" arguments:@[MGLConstantExpression(@-1.5)]];
+ NSArray *jsonExpression = @[@"round", @-1.5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-2);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_round:" arguments:@[MGLConstantExpression(@2.5)]];
+ NSArray *jsonExpression = @[@"round", @2.5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @3);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_round:" arguments:@[MGLConstantExpression(@-2.5)]];
+ NSArray *jsonExpression = @[@"round", @-2.5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @-3);
+ }
}
- (void)testTrigonometricExpressionObject {
@@ -450,41 +495,91 @@ using namespace std::string_literals;
NSExpression *expression = [NSExpression expressionForFunction:@"sqrt:" arguments:arguments];
NSArray *jsonExpression = @[@"sqrt", @1, @1];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"ln:" arguments:arguments];
NSArray *jsonExpression = @[@"ln", @1, @1];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_log2:" arguments:@[MGLConstantExpression(@1024)]];
+ NSArray *jsonExpression = @[@"log2", @1024];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @10);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"raise:toPower:" arguments:arguments];
NSArray *jsonExpression = @[@"^", @1, @1];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([NSExpression expressionWithFormat:@"1 ** 1"].mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"exp:" arguments:@[MGLConstantExpression(@0)]];
NSArray *jsonExpression = @[@"^", @[@"e"], @0];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @1);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionForConstantValue:@(M_E)];
NSArray *jsonExpression = @[@"e"];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @(M_E));
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionForConstantValue:@(M_PI)];
NSArray *jsonExpression = @[@"pi"];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @(M_PI));
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_acos:" arguments:@[MGLConstantExpression(@1)]];
+ NSArray *jsonExpression = @[@"acos", @1];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @0);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_cos:" arguments:@[MGLConstantExpression(@0)]];
+ NSArray *jsonExpression = @[@"cos", @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @1);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_asin:" arguments:@[MGLConstantExpression(@0)]];
+ NSArray *jsonExpression = @[@"asin", @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @0);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_sin:" arguments:@[MGLConstantExpression(@0)]];
+ NSArray *jsonExpression = @[@"sin", @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @0);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_atan:" arguments:@[MGLConstantExpression(@20)]];
+ NSArray *jsonExpression = @[@"atan", @20];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ NSNumber *value = [expression expressionValueWithObject:nil context:nil];
+ XCTAssertEqualWithAccuracy(value.doubleValue, 1.52, 0.001);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_tan:" arguments:@[MGLConstantExpression(@0)]];
+ NSArray *jsonExpression = @[@"tan", @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @0);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
}
@@ -492,22 +587,31 @@ using namespace std::string_literals;
NSArray *arguments = @[MGLConstantExpression(@"MacDonald")];
{
NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION('Old', 'stringByAppendingString:', 'MacDonald')"];
+ NSExpression *aftermarketExpression = [NSExpression expressionWithFormat:@"mgl_join({'Old', 'MacDonald'})"];
NSArray *jsonExpression = @[@"concat", @"Old", @"MacDonald"];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(aftermarketExpression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @"OldMacDonald");
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([aftermarketExpression expressionValueWithObject:nil context:nil], @"OldMacDonald");
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], aftermarketExpression);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"uppercase:" arguments:arguments];
NSArray *jsonExpression = @[@"upcase", @"MacDonald"];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionForFunction:@"lowercase:" arguments:arguments];
NSArray *jsonExpression = @[@"downcase", @"MacDonald"];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"length:" arguments:arguments];
+ NSArray *jsonExpression = @[@"length", @"MacDonald"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
}
@@ -518,7 +622,20 @@ using namespace std::string_literals;
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
// NSExpression is unable to evaluate -[NSNumber boolValue] by itself
// because it returns a primitive instead of an object.
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'mgl_number')"];
+ NSArray *jsonExpression = @[@"to-number", @[@"get", @"postalCode"]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'doubleValue')"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'floatValue')"].mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'decimalValue')"].mgl_jsonExpressionObject, jsonExpression);
+ // NSExpression is unable to evaluate NSNumber’s -floatValue,
+ // -doubleValue, or -decimalValue by themselves because they each return
+ // a primitive instead of an object.
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression],
+ [NSExpression expressionWithFormat:@"CAST(postalCode, 'NSNumber')"]);
}
{
NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'mgl_numberWithFallbackValues:', zipCode)"];
@@ -530,50 +647,117 @@ using namespace std::string_literals;
// NSExpression is unable to evaluate NSNumber’s -floatValue,
// -doubleValue, or -decimalValue by themselves because they each return
// a primitive instead of an object.
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
- NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(number, 'stringValue')"];
+ NSExpression *expression = [NSExpression expressionWithFormat:@"CAST(postalCode, 'NSNumber')"];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(postalCode, 'mgl_numberWithFallbackValues:')"];
+ NSArray *jsonExpression = @[@"to-number", @[@"get", @"postalCode"]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:@{@"postalCode": @"02134"} context:nil], @02134);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"CAST(number, 'NSString')"];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(number, 'stringValue')"];
NSArray *jsonExpression = @[@"to-string", @[@"get", @"number"]];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:@{@"number": @1.5} context:nil], @"1.5");
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([compatibilityExpression expressionValueWithObject:@{@"number": @1.5} context:nil], @"1.5");
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
}
- (void)testInterpolationExpressionObject {
{
NSDictionary *stops = @{@0: MGLConstantExpression(@100), @10: MGLConstantExpression(@200)};
- NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(x, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", stops];
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(x, 'linear', nil, %@)", stops];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(x, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", stops];
NSArray *jsonExpression = @[@"interpolate", @[@"linear"], @[@"get", @"x"], @0, @100, @10, @200];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSDictionary *stops = @{@1: MGLConstantExpression(@2), @3: MGLConstantExpression(@6)};
- NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(x, 'mgl_interpolateWithCurveType:parameters:stops:', 'exponential', 2, %@)", stops];
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(x, 'exponential', 2, %@)", stops];
NSArray *jsonExpression = @[@"interpolate", @[@"exponential", @2], @[@"get", @"x"], @1, @2, @3, @6];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSDictionary *stops = @{@0: MGLConstantExpression(@0), @100: MGLConstantExpression(@100)};
- NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(x, 'mgl_interpolateWithCurveType:parameters:stops:', 'cubic-bezier', { 0.42, 0, 0.58, 1 }, %@)", stops];
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(x, 'cubic-bezier', { 0.42, 0, 0.58, 1 }, %@)", stops];
NSArray *jsonExpression = @[@"interpolate", @[@"cubic-bezier", @0.42, @0, @0.58, @1], @[@"get", @"x"], @0, @0, @100, @100];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSDictionary *stops = @{@0: MGLConstantExpression(@111), @1: MGLConstantExpression(@1111)};
- NSExpression *expression = [NSExpression expressionWithFormat:@"FUNCTION(x, 'mgl_stepWithMinimum:stops:', 11, %@)", stops];
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(x, 11, %@)", stops];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(x, 'mgl_stepWithMinimum:stops:', 11, %@)", stops];
NSArray *jsonExpression = @[@"step", @[@"get", @"x"], @11, @0, @111, @1, @1111];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSDictionary *stops = @{@0: MGLConstantExpression(@111), @1: MGLConstantExpression(@1111)};
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, 11, %@)", stops];
+ NSArray *jsonExpression = @[@"step", @[@"zoom"], @11, @0, @111, @1, @1111];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
}
+- (void)testMatchExpressionObject {
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_MATCH(2 - 1, %@, %@, %@, %@, 'default')", MGLConstantExpression(@1),
+ MGLConstantExpression(@"one"),
+ MGLConstantExpression(@0),
+ MGLConstantExpression(@"zero")];
+ NSExpression *predicate = [NSExpression expressionWithFormat:@"2 - 1"];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(%@, 'mgl_match:', %@)", predicate, @[MGLConstantExpression(@1),
+ MGLConstantExpression(@"one"),
+ MGLConstantExpression(@0),
+ MGLConstantExpression(@"zero"),
+ MGLConstantExpression(@"default")]];
+ NSArray *jsonExpression = @[@"match", @[@"-", @2, @1], @1, @"one", @0, @"zero", @"default"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_MATCH(2 * 1, %@, %@, 'default')", MGLConstantExpression(@1), MGLConstantExpression(@"one")];
+ NSArray *jsonExpression = @[@"match", @[@"*", @2, @1], @1, @"one", @"default"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+}
+
+- (void)testCoalesceExpressionObject {
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_coalesce(%@)",
+ @[[NSExpression expressionForKeyPath:@"x"],
+ [NSExpression expressionForKeyPath:@"y"],
+ [NSExpression expressionForKeyPath:@"z"],
+ [NSExpression expressionForConstantValue:@0]]];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(%@, 'mgl_coalesce')", @[[NSExpression expressionForKeyPath:@"x"],
+ [NSExpression expressionForKeyPath:@"y"],
+ [NSExpression expressionForKeyPath:@"z"],
+ [NSExpression expressionForConstantValue:@0]]];
+ NSArray *jsonExpression = @[@"coalesce", @[@"get", @"x"], @[@"get", @"y"], @[@"get", @"z"], @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+
+}
+
- (void)testConditionalExpressionObject {
- // FIXME: This test crashes because iOS 8 doesn't have `+[NSExpression expressionForConditional:trueExpression:falseExpression:]`.
+ // This test crashes on iOS 8, which doesn't have `+[NSExpression expressionForConditional:trueExpression:falseExpression:]`.
// https://github.com/mapbox/mapbox-gl-native/issues/11007
if (@available(iOS 9.0, *)) {
{
@@ -585,16 +769,341 @@ using namespace std::string_literals;
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([NSExpression expressionWithFormat:@"TERNARY(1 = 2, TRUE, FALSE)"].mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @NO);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
}
{
NSExpression *expression = [NSExpression expressionWithFormat:@"TERNARY(0 = 1, TRUE, TERNARY(1 = 2, TRUE, FALSE))"];
NSArray *jsonExpression = @[@"case", @[@"==", @0, @1], @YES, @[@"==", @1, @2], @YES, @NO];
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @NO);
- XCTAssertEqualObjects([NSExpression mgl_expressionWithJSONObject:jsonExpression], expression);
+ expression = [NSExpression expressionWithFormat:@"MGL_IF(%@, TRUE, %@, TRUE, FALSE)",
+ MGLConstantExpression([NSPredicate predicateWithFormat:@"0 = 1"]),
+ MGLConstantExpression([NSPredicate predicateWithFormat:@"1 = 2"])];
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_IF(%@, %@, %@)",
+ [NSExpression expressionWithFormat:@"%@", [NSPredicate predicateWithFormat:@"1 = 2"]],
+ MGLConstantExpression(@YES),
+ MGLConstantExpression(@NO)];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(%@, 'mgl_if:', %@)", [NSPredicate predicateWithFormat:@"1 = 2"], @[MGLConstantExpression(@YES), MGLConstantExpression(@NO)]];
+ NSArray *jsonExpression = @[@"case", @[@"==", @1, @2], @YES, @NO];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ if (@available(iOS 9.0, *)) {
+ expression = [NSExpression expressionWithFormat:@"TERNARY(1 = 2, YES, NO)"];
+ }
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @NO);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_IF(%@, %@, %@, %@, %@)",
+ [NSExpression expressionWithFormat:@"%@", [NSPredicate predicateWithFormat:@"1 = 2"]],
+ MGLConstantExpression(@YES),
+ [NSExpression expressionWithFormat:@"%@", [NSPredicate predicateWithFormat:@"1 = 1"]],
+ MGLConstantExpression(@YES),
+ MGLConstantExpression(@NO)];
+ NSArray *jsonExpression = @[@"case", @[@"==", @1, @2], @YES, @[@"==", @1, @1], @YES, @NO];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @YES);
+ }
+ {
+ NSArray *jsonExpression = @[
+ @"case",
+ @[
+ @"<",
+ @[@"get", @"area"],
+ @80000
+ ],
+ @[@"get", @"abbr"],
+ @[@"get", @"name_en"]
+ ];
+ NSExpression *expression = [NSExpression expressionWithFormat:@"TERNARY(area < 80000, abbr, name_en)"];
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ }
+}
+
+- (void)testLookupExpressionObject {
+ {
+ NSExpression *array = [NSExpression expressionForAggregate:@[MGLConstantExpression(@9),
+ MGLConstantExpression(@8),
+ MGLConstantExpression(@7)]];
+ NSExpression *expression = [NSExpression expressionForFunction:@"objectFrom:withIndex:"
+ arguments:@[array, MGLConstantExpression(@1)]];
+ NSArray *jsonExpression = @[@"at", @1, @[ @"literal", @[@9, @8, @7]]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *array = [NSExpression expressionForAggregate:@[MGLConstantExpression(@9),
+ MGLConstantExpression(@8),
+ MGLConstantExpression(@7)]];
+ NSExpression *expression = [NSExpression expressionForFunction:@"objectFrom:withIndex:"
+ arguments:@[array, [NSExpression expressionForKeyPath:@"x"]]];
+ NSArray *jsonExpression = @[@"at", @[@"get", @"x"], @[ @"literal", @[@9, @8, @7]]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_does:have:"
+ arguments:@[[NSExpression expressionForEvaluatedObject],
+ [NSExpression expressionForConstantValue:@"x"]]];
+ NSExpression *compatibilityExpression = [NSExpression expressionWithFormat:@"FUNCTION(self, 'mgl_has:', 'x')"];
+ NSArray *jsonExpression = @[@"has", @"x"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_does:have:"
+ arguments:@[MGLConstantExpression(@{@"x": MGLConstantExpression(@0)}),
+ MGLConstantExpression(@"x")]];
+ NSArray *jsonExpression = @[@"has", @"x", @[@"literal", @{@"x": @0}]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [NSExpression expressionForFunction:@"mgl_does:have:"
+ arguments:@[[NSExpression expressionForVariable:@"featureAttributes"],
+ [NSExpression expressionForConstantValue:@"x"]]];
+ NSArray *jsonExpression = @[@"has", @"x", @[@"properties"]];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression;
+ if (@available(iOS 9.0, *)) {
+ expression = [NSExpression expressionWithFormat:@"TERNARY(key != nil, 1, 0)"];
+ } else {
+ expression = [NSExpression expressionWithFormat:@"MGL_IF(%@, 1, 0)",
+ MGLConstantExpression([NSPredicate predicateWithFormat:@"key != nil"])];
}
+ NSArray *jsonExpression = @[@"case", @[@"!=", @[@"get", @"key"], [NSNull null]], @1, @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:@{} context:nil], @NO);
+ XCTAssertEqualObjects([expression expressionValueWithObject:@{@"key": @"🗝"} context:nil], @YES);
+ }
+ {
+ NSDictionary *dictionary = @{@"key": @"🔑"};
+ NSExpression *expression;
+ if (@available(iOS 9.0, *)) {
+ expression = [NSExpression expressionWithFormat:@"TERNARY(%@.key != nil, 1, 0)", dictionary];
+ } else {
+ NSPredicate *conditional = [NSPredicate predicateWithFormat:@"%@.key != nil", dictionary];
+ expression = [NSExpression expressionWithFormat:@"MGL_IF(%@, 1, 0)",
+ MGLConstantExpression(conditional)];
+ }
+ NSArray *jsonExpression = @[@"case", @[@"!=", @[@"get", @"key", @[@"literal", dictionary]], [NSNull null]], @1, @0];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ // The dictionary isn’t equal enough.
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression].description, expression.description);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @YES);
+ }
+}
+
+- (void)testGenericExpressionObject {
+ {
+ NSExpression *expression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('random', 1, 2, 3, 4, 5)"];
+ NSArray *jsonExpression = @[@"random", @1, @2, @3, @4, @5];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ expression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('random', 1, 2, 3, 4)"];
+ XCTAssertThrowsSpecificNamed([expression expressionValueWithObject:nil context:nil], NSException, NSInvalidArgumentException);
+ }
+}
+
+#pragma mark - Localization tests
+
+- (void)testTokenReplacement {
+ {
+ NSExpression *original = MGLConstantExpression(@"");
+ NSExpression *expected = original;
+ XCTAssertEqualObjects(original.mgl_expressionByReplacingTokensWithKeyPaths, expected);
+ }
+ {
+ NSExpression *original = MGLConstantExpression(@"{");
+ NSExpression *expected = original;
+ XCTAssertEqualObjects(original.mgl_expressionByReplacingTokensWithKeyPaths, expected);
+ }
+ {
+ NSExpression *original = MGLConstantExpression(@"{token");
+ NSExpression *expected = original;
+ XCTAssertEqualObjects(original.mgl_expressionByReplacingTokensWithKeyPaths, expected);
+ }
+ {
+ NSExpression *original = MGLConstantExpression(@"{token}");
+ NSExpression *expected = [NSExpression expressionForKeyPath:@"token"];
+ XCTAssertEqualObjects(original.mgl_expressionByReplacingTokensWithKeyPaths, expected);
+ }
+ {
+ NSExpression *original = MGLConstantExpression(@"{token} {token}");
+ NSExpression *expected = [NSExpression expressionWithFormat:@"mgl_join({token, ' ', token})"];
+ XCTAssertEqualObjects(original.mgl_expressionByReplacingTokensWithKeyPaths, expected);
+ }
+ {
+ NSExpression *original = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, '{short}', %@)", @{
+ @1: MGLConstantExpression(@"{short}"),
+ @2: @"…",
+ @3: @"{long}",
+ }];
+ NSExpression *expected = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, short, %@)", @{
+ @1: [NSExpression expressionForKeyPath:@"short"],
+ @2: @"…",
+ @3: [NSExpression expressionForKeyPath:@"long"],
+ }];
+ XCTAssertEqualObjects(original.mgl_expressionByReplacingTokensWithKeyPaths, expected);
+ }
+}
+
+- (void)testLocalization {
+ {
+ NSExpression *original = MGLConstantExpression(@"");
+ NSExpression *expected = original;
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:nil], expected);
+ }
+ {
+ NSExpression *original = MGLConstantExpression(@"Old MacDonald");
+ NSExpression *expected = original;
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:nil], expected);
+ }
+ {
+ NSExpression *original = MGLConstantExpression(@"{name_en}");
+ NSExpression *expected = original;
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:nil], expected);
+ }
+ {
+ NSExpression *original = [NSExpression expressionForKeyPath:@"name_en"];
+ NSExpression *expected = original;
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:nil], expected);
+ }
+ {
+ NSExpression *original = [NSExpression expressionForKeyPath:@"name_en"];
+ NSExpression *expected = [NSExpression expressionForKeyPath:@"name"];
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:[NSLocale localeWithLocaleIdentifier:@"mul"]], expected);
+ }
+ {
+ NSExpression *original = [NSExpression expressionForKeyPath:@"name_en"];
+ NSExpression *expected = [NSExpression expressionForKeyPath:@"name_fr"];
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:[NSLocale localeWithLocaleIdentifier:@"fr-CA"]], expected);
+ }
+ {
+ NSExpression *original = [NSExpression expressionForKeyPath:@"name_en"];
+ NSExpression *expected = [NSExpression expressionForKeyPath:@"name_zh-Hans"];
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:[NSLocale localeWithLocaleIdentifier:@"zh-Hans"]], expected);
+ }
+ {
+ NSExpression *original = [NSExpression expressionForKeyPath:@"name_en"];
+ NSExpression *expected = [NSExpression expressionForKeyPath:@"name"];
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:[NSLocale localeWithLocaleIdentifier:@"tlh"]], expected);
+ }
+ {
+ NSExpression *original = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, short, %@)", @{
+ @1: [NSExpression expressionForKeyPath:@"abbr"],
+ @2: @"…",
+ @3: [NSExpression expressionForKeyPath:@"name_fr"],
+ }];
+ NSExpression *expected = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, short, %@)", @{
+ @1: [NSExpression expressionForKeyPath:@"abbr"],
+ @2: @"…",
+ @3: [NSExpression expressionForKeyPath:@"name_es"],
+ }];
+ XCTAssertEqualObjects([original mgl_expressionLocalizedIntoLocale:[NSLocale localeWithLocaleIdentifier:@"es-PR"]], expected);
+ }
+ {
+ NSArray *jsonExpression = @[
+ @"step",
+ @[@"zoom"],
+ @[
+ @"case",
+ @[
+ @"<",
+ @[
+ @"to-number",
+ @[@"get", @"area"]
+ ],
+ @80000
+ ],
+ @[@"get", @"abbr"],
+ @[@"get", @"name_en"]
+ ],
+ @5, @[@"get", @"name_en"]
+ ];
+ NSArray *localizedJSONExpression = @[
+ @"step",
+ @[@"zoom"],
+ @[
+ @"case",
+ @[
+ @"<",
+ @[
+ @"to-number",
+ @[@"get", @"area"]
+ ],
+ @80000
+ ],
+ @[@"get", @"abbr"],
+ @[@"get", @"name"]
+ ],
+ @5, @[@"get", @"name"]
+ ];
+ NSExpression *expression = [NSExpression expressionWithMGLJSONObject:jsonExpression];
+ NSExpression *localizedExpression = [expression mgl_expressionLocalizedIntoLocale:[NSLocale localeWithLocaleIdentifier:@"mul"]];
+ XCTAssertEqualObjects(localizedExpression.mgl_jsonExpressionObject, localizedJSONExpression);
}
}
+- (void)testConvenienceInitializers {
+ {
+ NSExpression *expression = [NSExpression mgl_expressionForConditional:[NSPredicate predicateWithFormat:@"1 = 2"]
+ trueExpression:MGLConstantExpression(@YES)
+ falseExpresssion:MGLConstantExpression(@NO)];
+
+ NSArray *jsonExpression = @[@"case", @[@"==", @1, @2], @YES, @NO];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @NO);
+ }
+ {
+ NSDictionary *stops = @{@0: MGLConstantExpression(@111), @1: MGLConstantExpression(@1111)};
+ NSExpression *expression = [NSExpression mgl_expressionForSteppingExpression:[NSExpression expressionForKeyPath:@"x"]
+ fromExpression:[NSExpression expressionForConstantValue:@11]
+ stops:[NSExpression expressionForConstantValue:stops]];
+ NSArray *jsonExpression = @[@"step", @[@"get", @"x"], @11, @0, @111, @1, @1111];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSDictionary *stops = @{@0: MGLConstantExpression(@100), @10: MGLConstantExpression(@200)};
+ NSExpression *expression = [NSExpression mgl_expressionForInterpolatingExpression:[NSExpression expressionForKeyPath:@"x"]
+ withCurveType:MGLExpressionInterpolationModeLinear
+ parameters:nil
+ stops:[NSExpression expressionForConstantValue:stops]];
+ NSArray *jsonExpression = @[@"interpolate", @[@"linear"], @[@"get", @"x"], @0, @100, @10, @200];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSExpression *expression = [[NSExpression expressionForConstantValue:@"Old"] mgl_expressionByAppendingExpression:[NSExpression expressionForConstantValue:@"MacDonald"]];
+
+ NSArray *jsonExpression = @[@"concat", @"Old", @"MacDonald"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([expression expressionValueWithObject:nil context:nil], @"OldMacDonald");
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+ {
+ NSDictionary *values = @{ MGLConstantExpression(@1): MGLConstantExpression(@"one") };
+ NSExpression *expression = [NSExpression mgl_expressionForMatchingExpression:[NSExpression expressionWithFormat:@"2 * 1"]
+ inDictionary:values
+ defaultExpression:[NSExpression expressionForConstantValue:@"default"]];
+ NSArray *jsonExpression = @[@"match", @[@"*", @2, @1], @1, @"one", @"default"];
+ XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
+ }
+}
+
+
@end
diff --git a/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm b/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm
index f5e26381d6..6081d104e1 100644
--- a/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm
+++ b/platform/darwin/test/MGLFillExtrusionStyleLayerTests.mm
@@ -30,8 +30,8 @@
XCTAssertNil(layer.sourceLayerIdentifier);
XCTAssertNil(layer.predicate);
- layer.predicate = [NSPredicate predicateWithValue:NO];
- XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
+ layer.predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"]);
layer.predicate = nil;
XCTAssertNil(layer.predicate);
}
@@ -63,7 +63,7 @@
@"fillExtrusionBase should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.fillExtrusionBase = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -77,7 +77,7 @@
XCTAssertEqualObjects(layer.fillExtrusionBase, functionExpression,
@"fillExtrusionBase should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.fillExtrusionBase = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -85,10 +85,11 @@
XCTAssertEqual(rawLayer->getFillExtrusionBase(), propertyValue,
@"Setting fillExtrusionBase to a data expression should update fill-extrusion-base.");
- XCTAssertEqualObjects(layer.fillExtrusionBase, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionBase, pedanticFunctionExpression,
@"fillExtrusionBase should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.fillExtrusionBase = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -98,7 +99,8 @@
XCTAssertEqual(rawLayer->getFillExtrusionBase(), propertyValue,
@"Setting fillExtrusionBase to a camera-data expression should update fill-extrusion-base.");
- XCTAssertEqualObjects(layer.fillExtrusionBase, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionBase, pedanticFunctionExpression,
@"fillExtrusionBase should round-trip camera-data expressions.");
@@ -133,7 +135,7 @@
@"fillExtrusionColor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.fillExtrusionColor = functionExpression;
mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
@@ -147,7 +149,7 @@
XCTAssertEqualObjects(layer.fillExtrusionColor, functionExpression,
@"fillExtrusionColor should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.fillExtrusionColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
@@ -155,10 +157,11 @@
XCTAssertEqual(rawLayer->getFillExtrusionColor(), propertyValue,
@"Setting fillExtrusionColor to a data expression should update fill-extrusion-color.");
- XCTAssertEqualObjects(layer.fillExtrusionColor, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionColor, pedanticFunctionExpression,
@"fillExtrusionColor should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.fillExtrusionColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
@@ -168,7 +171,8 @@
XCTAssertEqual(rawLayer->getFillExtrusionColor(), propertyValue,
@"Setting fillExtrusionColor to a camera-data expression should update fill-extrusion-color.");
- XCTAssertEqualObjects(layer.fillExtrusionColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionColor, pedanticFunctionExpression,
@"fillExtrusionColor should round-trip camera-data expressions.");
@@ -203,7 +207,7 @@
@"fillExtrusionHeight should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.fillExtrusionHeight = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -217,7 +221,7 @@
XCTAssertEqualObjects(layer.fillExtrusionHeight, functionExpression,
@"fillExtrusionHeight should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.fillExtrusionHeight = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -225,10 +229,11 @@
XCTAssertEqual(rawLayer->getFillExtrusionHeight(), propertyValue,
@"Setting fillExtrusionHeight to a data expression should update fill-extrusion-height.");
- XCTAssertEqualObjects(layer.fillExtrusionHeight, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionHeight, pedanticFunctionExpression,
@"fillExtrusionHeight should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.fillExtrusionHeight = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -238,7 +243,8 @@
XCTAssertEqual(rawLayer->getFillExtrusionHeight(), propertyValue,
@"Setting fillExtrusionHeight to a camera-data expression should update fill-extrusion-height.");
- XCTAssertEqualObjects(layer.fillExtrusionHeight, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillExtrusionHeight, pedanticFunctionExpression,
@"fillExtrusionHeight should round-trip camera-data expressions.");
@@ -273,7 +279,7 @@
@"fillExtrusionOpacity should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.fillExtrusionOpacity = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -297,8 +303,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.fillExtrusionOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.fillExtrusionOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.fillExtrusionOpacityTransition = transitionTest;
@@ -326,7 +332,7 @@
@"fillExtrusionPattern should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'Fill Extrusion Pattern'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.fillExtrusionPattern = functionExpression;
mbgl::style::IntervalStops<std::string> intervalStops = {{
@@ -350,8 +356,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.fillExtrusionPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.fillExtrusionPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.fillExtrusionPatternTransition = transitionTest;
@@ -385,7 +391,7 @@
@"fillExtrusionTranslation should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.fillExtrusionTranslation = functionExpression;
mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
@@ -409,8 +415,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -429,7 +435,7 @@
@"fillExtrusionTranslationAnchor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.fillExtrusionTranslationAnchor = functionExpression;
mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = {{
@@ -453,8 +459,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.fillExtrusionTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillExtrusionLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
}
diff --git a/platform/darwin/test/MGLFillStyleLayerTests.mm b/platform/darwin/test/MGLFillStyleLayerTests.mm
index 25521f3ede..a5019f1032 100644
--- a/platform/darwin/test/MGLFillStyleLayerTests.mm
+++ b/platform/darwin/test/MGLFillStyleLayerTests.mm
@@ -30,8 +30,8 @@
XCTAssertNil(layer.sourceLayerIdentifier);
XCTAssertNil(layer.predicate);
- layer.predicate = [NSPredicate predicateWithValue:NO];
- XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
+ layer.predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"]);
layer.predicate = nil;
XCTAssertNil(layer.predicate);
}
@@ -63,7 +63,7 @@
@"fillAntialiased should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"false"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.fillAntialiased = functionExpression;
mbgl::style::IntervalStops<bool> intervalStops = {{
@@ -87,8 +87,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.fillAntialiased = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.fillAntialiased = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -107,7 +107,7 @@
@"fillColor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.fillColor = functionExpression;
mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
@@ -121,7 +121,7 @@
XCTAssertEqualObjects(layer.fillColor, functionExpression,
@"fillColor should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.fillColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
@@ -129,10 +129,11 @@
XCTAssertEqual(rawLayer->getFillColor(), propertyValue,
@"Setting fillColor to a data expression should update fill-color.");
- XCTAssertEqualObjects(layer.fillColor, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.fillColor, pedanticFunctionExpression,
@"fillColor should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.fillColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
@@ -142,7 +143,8 @@
XCTAssertEqual(rawLayer->getFillColor(), propertyValue,
@"Setting fillColor to a camera-data expression should update fill-color.");
- XCTAssertEqualObjects(layer.fillColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillColor, pedanticFunctionExpression,
@"fillColor should round-trip camera-data expressions.");
@@ -177,7 +179,7 @@
@"fillOpacity should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.fillOpacity = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -191,7 +193,7 @@
XCTAssertEqualObjects(layer.fillOpacity, functionExpression,
@"fillOpacity should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.fillOpacity = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -199,10 +201,11 @@
XCTAssertEqual(rawLayer->getFillOpacity(), propertyValue,
@"Setting fillOpacity to a data expression should update fill-opacity.");
- XCTAssertEqualObjects(layer.fillOpacity, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.fillOpacity, pedanticFunctionExpression,
@"fillOpacity should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.fillOpacity = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -212,7 +215,8 @@
XCTAssertEqual(rawLayer->getFillOpacity(), propertyValue,
@"Setting fillOpacity to a camera-data expression should update fill-opacity.");
- XCTAssertEqualObjects(layer.fillOpacity, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillOpacity, pedanticFunctionExpression,
@"fillOpacity should round-trip camera-data expressions.");
@@ -247,7 +251,7 @@
@"fillOutlineColor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.fillOutlineColor = functionExpression;
mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
@@ -261,7 +265,7 @@
XCTAssertEqualObjects(layer.fillOutlineColor, functionExpression,
@"fillOutlineColor should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.fillOutlineColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
@@ -269,10 +273,11 @@
XCTAssertEqual(rawLayer->getFillOutlineColor(), propertyValue,
@"Setting fillOutlineColor to a data expression should update fill-outline-color.");
- XCTAssertEqualObjects(layer.fillOutlineColor, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.fillOutlineColor, pedanticFunctionExpression,
@"fillOutlineColor should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.fillOutlineColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
@@ -282,7 +287,8 @@
XCTAssertEqual(rawLayer->getFillOutlineColor(), propertyValue,
@"Setting fillOutlineColor to a camera-data expression should update fill-outline-color.");
- XCTAssertEqualObjects(layer.fillOutlineColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.fillOutlineColor, pedanticFunctionExpression,
@"fillOutlineColor should round-trip camera-data expressions.");
@@ -317,7 +323,7 @@
@"fillPattern should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'Fill Pattern'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.fillPattern = functionExpression;
mbgl::style::IntervalStops<std::string> intervalStops = {{
@@ -341,8 +347,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.fillPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.fillPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.fillPatternTransition = transitionTest;
@@ -376,7 +382,7 @@
@"fillTranslation should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.fillTranslation = functionExpression;
mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
@@ -400,8 +406,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.fillTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.fillTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -420,7 +426,7 @@
@"fillTranslationAnchor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.fillTranslationAnchor = functionExpression;
mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = {{
@@ -444,8 +450,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.fillTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.fillTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLFillLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
}
diff --git a/platform/darwin/test/MGLGeometryTests.mm b/platform/darwin/test/MGLGeometryTests.mm
index 1c85470188..a0ddecf77e 100644
--- a/platform/darwin/test/MGLGeometryTests.mm
+++ b/platform/darwin/test/MGLGeometryTests.mm
@@ -163,4 +163,13 @@
[NSValue valueWithMGLCoordinate:quad.bottomRight],
@"Quad bottom right should be computed correctly.");
}
+
+- (void)testMGLMapPoint {
+ MGLMapPoint point = MGLMapPointForCoordinate(CLLocationCoordinate2DMake(37.936, -80.425), 0.0);
+
+ MGLMapPoint roundTrippedPoint = [NSValue valueWithMGLMapPoint:point].MGLMapPointValue;
+ XCTAssertEqual(point.x, roundTrippedPoint.x);
+ XCTAssertEqual(point.y, roundTrippedPoint.y);
+ XCTAssertEqual(point.zoomLevel, roundTrippedPoint.zoomLevel);
+}
@end
diff --git a/platform/darwin/test/MGLHeatmapColorTests.mm b/platform/darwin/test/MGLHeatmapColorTests.mm
index 8d44064d94..bed777ae05 100644
--- a/platform/darwin/test/MGLHeatmapColorTests.mm
+++ b/platform/darwin/test/MGLHeatmapColorTests.mm
@@ -33,7 +33,7 @@
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
NSExpression *constantExpression2 = [NSExpression expressionWithFormat:@"%@", [MGLColor blueColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($heatmapDensity, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@12: constantExpression2}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($heatmapDensity, %@, %@)", constantExpression, @{@12: constantExpression2}];
layer.heatmapColor = functionExpression;
XCTAssertEqual(rawLayer->getHeatmapColor().evaluate(11.0), mbgl::Color::red(),
@@ -46,15 +46,16 @@
layer.heatmapColor = nil;
XCTAssertTrue(rawLayer->getHeatmapColor().isUndefined(),
@"Unsetting heatmapColor should return heatmap-color to the default value.");
- XCTAssertEqualObjects(layer.heatmapColor, defaultExpression,
+ // The contained colors aren’t object equal, even though their descriptions are.
+ XCTAssertEqualObjects(layer.heatmapColor.description, defaultExpression.description,
@"heatmapColor should return the default value after being unset.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
XCTAssertThrowsSpecificNamed(layer.heatmapColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera expression is applied to heatmapColor.");
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.heatmapColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a data expression is applied to heatmapColor.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.heatmapColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
diff --git a/platform/darwin/test/MGLHeatmapStyleLayerTests.mm b/platform/darwin/test/MGLHeatmapStyleLayerTests.mm
index 74121affd8..e4b1917257 100644
--- a/platform/darwin/test/MGLHeatmapStyleLayerTests.mm
+++ b/platform/darwin/test/MGLHeatmapStyleLayerTests.mm
@@ -30,8 +30,8 @@
XCTAssertNil(layer.sourceLayerIdentifier);
XCTAssertNil(layer.predicate);
- layer.predicate = [NSPredicate predicateWithValue:NO];
- XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
+ layer.predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"]);
layer.predicate = nil;
XCTAssertNil(layer.predicate);
}
@@ -63,7 +63,7 @@
@"heatmapIntensity should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.heatmapIntensity = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -87,8 +87,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.heatmapIntensity = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.heatmapIntensity = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.heatmapIntensityTransition = transitionTest;
@@ -116,7 +116,7 @@
@"heatmapOpacity should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.heatmapOpacity = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -140,8 +140,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.heatmapOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.heatmapOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLHeatmapLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.heatmapOpacityTransition = transitionTest;
@@ -169,7 +169,7 @@
@"heatmapRadius should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.heatmapRadius = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -183,7 +183,7 @@
XCTAssertEqualObjects(layer.heatmapRadius, functionExpression,
@"heatmapRadius should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.heatmapRadius = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -191,10 +191,11 @@
XCTAssertEqual(rawLayer->getHeatmapRadius(), propertyValue,
@"Setting heatmapRadius to a data expression should update heatmap-radius.");
- XCTAssertEqualObjects(layer.heatmapRadius, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.heatmapRadius, pedanticFunctionExpression,
@"heatmapRadius should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.heatmapRadius = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -204,7 +205,8 @@
XCTAssertEqual(rawLayer->getHeatmapRadius(), propertyValue,
@"Setting heatmapRadius to a camera-data expression should update heatmap-radius.");
- XCTAssertEqualObjects(layer.heatmapRadius, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.heatmapRadius, pedanticFunctionExpression,
@"heatmapRadius should round-trip camera-data expressions.");
@@ -239,7 +241,7 @@
@"heatmapWeight should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.heatmapWeight = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -253,7 +255,7 @@
XCTAssertEqualObjects(layer.heatmapWeight, functionExpression,
@"heatmapWeight should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.heatmapWeight = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -261,10 +263,11 @@
XCTAssertEqual(rawLayer->getHeatmapWeight(), propertyValue,
@"Setting heatmapWeight to a data expression should update heatmap-weight.");
- XCTAssertEqualObjects(layer.heatmapWeight, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.heatmapWeight, pedanticFunctionExpression,
@"heatmapWeight should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.heatmapWeight = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -274,7 +277,8 @@
XCTAssertEqual(rawLayer->getHeatmapWeight(), propertyValue,
@"Setting heatmapWeight to a camera-data expression should update heatmap-weight.");
- XCTAssertEqualObjects(layer.heatmapWeight, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.heatmapWeight, pedanticFunctionExpression,
@"heatmapWeight should round-trip camera-data expressions.");
diff --git a/platform/darwin/test/MGLHillshadeStyleLayerTests.mm b/platform/darwin/test/MGLHillshadeStyleLayerTests.mm
index b0b7ddd5ee..34937d1674 100644
--- a/platform/darwin/test/MGLHillshadeStyleLayerTests.mm
+++ b/platform/darwin/test/MGLHillshadeStyleLayerTests.mm
@@ -45,7 +45,7 @@
@"hillshadeAccentColor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.hillshadeAccentColor = functionExpression;
mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
@@ -69,8 +69,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.hillshadeAccentColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.hillshadeAccentColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.hillshadeAccentColorTransition = transitionTest;
@@ -98,7 +98,7 @@
@"hillshadeExaggeration should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.hillshadeExaggeration = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -122,8 +122,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.hillshadeExaggeration = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.hillshadeExaggeration = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.hillshadeExaggerationTransition = transitionTest;
@@ -151,7 +151,7 @@
@"hillshadeHighlightColor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.hillshadeHighlightColor = functionExpression;
mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
@@ -175,8 +175,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.hillshadeHighlightColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.hillshadeHighlightColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.hillshadeHighlightColorTransition = transitionTest;
@@ -204,7 +204,7 @@
@"hillshadeIlluminationAnchor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.hillshadeIlluminationAnchor = functionExpression;
mbgl::style::IntervalStops<mbgl::style::HillshadeIlluminationAnchorType> intervalStops = {{
@@ -228,8 +228,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.hillshadeIlluminationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.hillshadeIlluminationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -248,7 +248,7 @@
@"hillshadeIlluminationDirection should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.hillshadeIlluminationDirection = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -272,8 +272,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.hillshadeIlluminationDirection = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.hillshadeIlluminationDirection = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -292,7 +292,7 @@
@"hillshadeShadowColor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.hillshadeShadowColor = functionExpression;
mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
@@ -316,8 +316,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.hillshadeShadowColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.hillshadeShadowColor = functionExpression, NSException, NSInvalidArgumentException, @"MGLHillshadeLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.hillshadeShadowColorTransition = transitionTest;
diff --git a/platform/darwin/test/MGLLineStyleLayerTests.mm b/platform/darwin/test/MGLLineStyleLayerTests.mm
index bf98e98320..5490278e98 100644
--- a/platform/darwin/test/MGLLineStyleLayerTests.mm
+++ b/platform/darwin/test/MGLLineStyleLayerTests.mm
@@ -30,8 +30,8 @@
XCTAssertNil(layer.sourceLayerIdentifier);
XCTAssertNil(layer.predicate);
- layer.predicate = [NSPredicate predicateWithValue:NO];
- XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
+ layer.predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"]);
layer.predicate = nil;
XCTAssertNil(layer.predicate);
}
@@ -63,7 +63,7 @@
@"lineCap should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'square'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.lineCap = functionExpression;
mbgl::style::IntervalStops<mbgl::style::LineCapType> intervalStops = {{
@@ -87,8 +87,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.lineCap = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.lineCap = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -107,7 +107,7 @@
@"lineJoin should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'miter'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.lineJoin = functionExpression;
mbgl::style::IntervalStops<mbgl::style::LineJoinType> intervalStops = {{
@@ -145,7 +145,7 @@
@"lineMiterLimit should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.lineMiterLimit = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -169,8 +169,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.lineMiterLimit = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.lineMiterLimit = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -189,7 +189,7 @@
@"lineRoundLimit should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.lineRoundLimit = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -213,8 +213,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.lineRoundLimit = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.lineRoundLimit = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -233,7 +233,7 @@
@"lineBlur should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.lineBlur = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -247,7 +247,7 @@
XCTAssertEqualObjects(layer.lineBlur, functionExpression,
@"lineBlur should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.lineBlur = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -255,10 +255,11 @@
XCTAssertEqual(rawLayer->getLineBlur(), propertyValue,
@"Setting lineBlur to a data expression should update line-blur.");
- XCTAssertEqualObjects(layer.lineBlur, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.lineBlur, pedanticFunctionExpression,
@"lineBlur should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.lineBlur = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -268,7 +269,8 @@
XCTAssertEqual(rawLayer->getLineBlur(), propertyValue,
@"Setting lineBlur to a camera-data expression should update line-blur.");
- XCTAssertEqualObjects(layer.lineBlur, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineBlur, pedanticFunctionExpression,
@"lineBlur should round-trip camera-data expressions.");
@@ -303,7 +305,7 @@
@"lineColor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.lineColor = functionExpression;
mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
@@ -317,7 +319,7 @@
XCTAssertEqualObjects(layer.lineColor, functionExpression,
@"lineColor should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.lineColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
@@ -325,10 +327,11 @@
XCTAssertEqual(rawLayer->getLineColor(), propertyValue,
@"Setting lineColor to a data expression should update line-color.");
- XCTAssertEqualObjects(layer.lineColor, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.lineColor, pedanticFunctionExpression,
@"lineColor should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.lineColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
@@ -338,7 +341,8 @@
XCTAssertEqual(rawLayer->getLineColor(), propertyValue,
@"Setting lineColor to a camera-data expression should update line-color.");
- XCTAssertEqualObjects(layer.lineColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineColor, pedanticFunctionExpression,
@"lineColor should round-trip camera-data expressions.");
@@ -373,7 +377,7 @@
@"lineDashPattern should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"{1, 2}"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.lineDashPattern = functionExpression;
mbgl::style::IntervalStops<std::vector<float>> intervalStops = {{
@@ -397,8 +401,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.lineDashPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.lineDashPattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -417,7 +421,7 @@
@"lineGapWidth should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.lineGapWidth = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -431,7 +435,7 @@
XCTAssertEqualObjects(layer.lineGapWidth, functionExpression,
@"lineGapWidth should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.lineGapWidth = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -439,10 +443,11 @@
XCTAssertEqual(rawLayer->getLineGapWidth(), propertyValue,
@"Setting lineGapWidth to a data expression should update line-gap-width.");
- XCTAssertEqualObjects(layer.lineGapWidth, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.lineGapWidth, pedanticFunctionExpression,
@"lineGapWidth should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.lineGapWidth = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -452,7 +457,8 @@
XCTAssertEqual(rawLayer->getLineGapWidth(), propertyValue,
@"Setting lineGapWidth to a camera-data expression should update line-gap-width.");
- XCTAssertEqualObjects(layer.lineGapWidth, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineGapWidth, pedanticFunctionExpression,
@"lineGapWidth should round-trip camera-data expressions.");
@@ -487,7 +493,7 @@
@"lineOffset should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.lineOffset = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -501,7 +507,7 @@
XCTAssertEqualObjects(layer.lineOffset, functionExpression,
@"lineOffset should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.lineOffset = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -509,10 +515,11 @@
XCTAssertEqual(rawLayer->getLineOffset(), propertyValue,
@"Setting lineOffset to a data expression should update line-offset.");
- XCTAssertEqualObjects(layer.lineOffset, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.lineOffset, pedanticFunctionExpression,
@"lineOffset should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.lineOffset = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -522,7 +529,8 @@
XCTAssertEqual(rawLayer->getLineOffset(), propertyValue,
@"Setting lineOffset to a camera-data expression should update line-offset.");
- XCTAssertEqualObjects(layer.lineOffset, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineOffset, pedanticFunctionExpression,
@"lineOffset should round-trip camera-data expressions.");
@@ -557,7 +565,7 @@
@"lineOpacity should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.lineOpacity = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -571,7 +579,7 @@
XCTAssertEqualObjects(layer.lineOpacity, functionExpression,
@"lineOpacity should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.lineOpacity = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -579,10 +587,11 @@
XCTAssertEqual(rawLayer->getLineOpacity(), propertyValue,
@"Setting lineOpacity to a data expression should update line-opacity.");
- XCTAssertEqualObjects(layer.lineOpacity, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.lineOpacity, pedanticFunctionExpression,
@"lineOpacity should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.lineOpacity = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -592,7 +601,8 @@
XCTAssertEqual(rawLayer->getLineOpacity(), propertyValue,
@"Setting lineOpacity to a camera-data expression should update line-opacity.");
- XCTAssertEqualObjects(layer.lineOpacity, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineOpacity, pedanticFunctionExpression,
@"lineOpacity should round-trip camera-data expressions.");
@@ -627,7 +637,7 @@
@"linePattern should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'Line Pattern'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.linePattern = functionExpression;
mbgl::style::IntervalStops<std::string> intervalStops = {{
@@ -651,8 +661,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.linePattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.linePattern = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.linePatternTransition = transitionTest;
@@ -686,7 +696,7 @@
@"lineTranslation should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.lineTranslation = functionExpression;
mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
@@ -710,8 +720,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.lineTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.lineTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -730,7 +740,7 @@
@"lineTranslationAnchor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.lineTranslationAnchor = functionExpression;
mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = {{
@@ -754,8 +764,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.lineTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.lineTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLLineLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -774,7 +784,7 @@
@"lineWidth should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.lineWidth = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -788,7 +798,7 @@
XCTAssertEqualObjects(layer.lineWidth, functionExpression,
@"lineWidth should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.lineWidth = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -796,10 +806,11 @@
XCTAssertEqual(rawLayer->getLineWidth(), propertyValue,
@"Setting lineWidth to a data expression should update line-width.");
- XCTAssertEqualObjects(layer.lineWidth, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.lineWidth, pedanticFunctionExpression,
@"lineWidth should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.lineWidth = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -809,7 +820,8 @@
XCTAssertEqual(rawLayer->getLineWidth(), propertyValue,
@"Setting lineWidth to a camera-data expression should update line-width.");
- XCTAssertEqualObjects(layer.lineWidth, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.lineWidth, pedanticFunctionExpression,
@"lineWidth should round-trip camera-data expressions.");
diff --git a/platform/darwin/test/MGLPredicateTests.mm b/platform/darwin/test/MGLPredicateTests.mm
index d8cad0b166..ab4a7e2d88 100644
--- a/platform/darwin/test/MGLPredicateTests.mm
+++ b/platform/darwin/test/MGLPredicateTests.mm
@@ -23,295 +23,9 @@ namespace mbgl {
@implementation MGLPredicateTests
-- (void)testFilterization {
- {
- auto actual = [NSPredicate predicateWithValue:YES].mgl_filter;
- mbgl::style::AllFilter expected;
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithValue:NO].mgl_filter;
- mbgl::style::AnyFilter expected;
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a = 'b'"].mgl_filter;
- mbgl::style::EqualsFilter expected = { .key = "a", .value = std::string("b") };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K = 'Point'", @"$type"].mgl_filter;
- mbgl::style::TypeEqualsFilter expected = { .value = mbgl::FeatureType::Point };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K = 67086180", @"$id"].mgl_filter;
- mbgl::style::IdentifierEqualsFilter expected = { .value = UINT64_C(67086180) };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K = nil", @"$id"].mgl_filter;
- mbgl::style::NotHasIdentifierFilter expected;
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a = nil"].mgl_filter;
- mbgl::style::NotHasFilter expected = { .key = "a" };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K != 'Point'", @"$type"].mgl_filter;
- mbgl::style::TypeNotEqualsFilter expected = { .value = mbgl::FeatureType::Point };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K != 67086180", @"$id"].mgl_filter;
- mbgl::style::IdentifierNotEqualsFilter expected = { .value = UINT64_C(67086180) };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K != nil", @"$id"].mgl_filter;
- mbgl::style::HasIdentifierFilter expected;
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a != 'b'"].mgl_filter;
- mbgl::style::NotEqualsFilter expected = { .key = "a", .value = std::string("b") };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a != nil"].mgl_filter;
- mbgl::style::HasFilter expected = { .key = "a" };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a < 'b'"].mgl_filter;
- mbgl::style::LessThanFilter expected = { .key = "a", .value = std::string("b") };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a <= 'b'"].mgl_filter;
- mbgl::style::LessThanEqualsFilter expected = { .key = "a", .value = std::string("b") };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a > 'b'"].mgl_filter;
- mbgl::style::GreaterThanFilter expected = { .key = "a", .value = std::string("b") };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a >= 'b'"].mgl_filter;
- mbgl::style::GreaterThanEqualsFilter expected = { .key = "a", .value = std::string("b") };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a BETWEEN {'b', 'z'}"].mgl_filter;
- mbgl::style::AllFilter expected = {
- .filters = {
- mbgl::style::GreaterThanEqualsFilter { .key = "a", .value = std::string("b") },
- mbgl::style::LessThanEqualsFilter { .key = "a", .value = std::string("z") },
- },
- };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a BETWEEN %@", @[@"b", @"z"]].mgl_filter;
- mbgl::style::AllFilter expected = {
- .filters = {
- mbgl::style::GreaterThanEqualsFilter { .key = "a", .value = std::string("b") },
- mbgl::style::LessThanEqualsFilter { .key = "a", .value = std::string("z") },
- },
- };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a IN {'b', 'c'}"].mgl_filter;
- mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a IN %@", @[@"b", @"c"]].mgl_filter;
- mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K IN {'LineString', 'Polygon'}", @"$type"].mgl_filter;
- mbgl::style::TypeInFilter expected = { .values = { mbgl::FeatureType::LineString, mbgl::FeatureType::Polygon } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K IN %@", @"$type", @[@"LineString", @"Polygon"]].mgl_filter;
- mbgl::style::TypeInFilter expected = { .values = { mbgl::FeatureType::LineString, mbgl::FeatureType::Polygon } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K IN {67086180, 3709678893, 3352016856, 4189833989}", @"$id"].mgl_filter;
- mbgl::style::IdentifierInFilter expected = { .values = { UINT64_C(67086180), UINT64_C(3709678893), UINT64_C(3352016856), UINT64_C(4189833989) } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%K IN %@", @"$id", @[@67086180, @3709678893, @3352016856, @4189833989]].mgl_filter;
- mbgl::style::IdentifierInFilter expected = { .values = { UINT64_C(67086180), UINT64_C(3709678893), UINT64_C(3352016856), UINT64_C(4189833989) } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"'Mapbox' IN a"].mgl_filter, NSException, NSInvalidArgumentException);
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"{'b', 'c'} CONTAINS a"].mgl_filter;
- mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@"b", @"c"]].mgl_filter;
- mbgl::style::InFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%@ CONTAINS %K", @[@"LineString", @"Polygon"], @"$type"].mgl_filter;
- mbgl::style::TypeInFilter expected = { .values = { mbgl::FeatureType::LineString, mbgl::FeatureType::Polygon } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"{67086180, 3709678893, 3352016856, 4189833989} CONTAINS %K", @"$id"].mgl_filter;
- mbgl::style::IdentifierInFilter expected = { .values = { UINT64_C(67086180), UINT64_C(3709678893), UINT64_C(3352016856), UINT64_C(4189833989) } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"%@ CONTAINS %K", @[@67086180, @3709678893, @3352016856, @4189833989], @"$id"].mgl_filter;
- mbgl::style::IdentifierInFilter expected = { .values = { UINT64_C(67086180), UINT64_C(3709678893), UINT64_C(3352016856), UINT64_C(4189833989) } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a CONTAINS 'Mapbox'"].mgl_filter, NSException, NSInvalidArgumentException);
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a == 'b' AND c == 'd'"].mgl_filter;
- mbgl::style::AllFilter expected = {
- .filters = {
- mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") },
- mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") },
- },
- };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"a == 'b' OR c == 'd'"].mgl_filter;
- mbgl::style::AnyFilter expected = {
- .filters = {
- mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") },
- mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") },
- },
- };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT(a == 'b' AND c == 'd')"].mgl_filter;
- mbgl::style::NoneFilter expected = {
- .filters = {
- mbgl::style::AllFilter {
- .filters = {
- mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") },
- mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") },
- },
- },
- },
- };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT(a == 'b' OR c == 'd')"].mgl_filter;
- mbgl::style::NoneFilter expected = {
- .filters = {
- mbgl::style::EqualsFilter { .key = "a", .value = std::string("b") },
- mbgl::style::EqualsFilter { .key = "c", .value = std::string("d") },
- },
- };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT a == nil"].mgl_filter;
- mbgl::style::HasFilter expected = { .key = "a" };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT a != nil"].mgl_filter;
- mbgl::style::NotHasFilter expected = { .key = "a" };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT a IN {'b', 'c'}"].mgl_filter;
- mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT a IN %@", @[@"b", @"c"]].mgl_filter;
- mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT {'b', 'c'} CONTAINS a"].mgl_filter;
- mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- {
- auto actual = [NSPredicate predicateWithFormat:@"NOT %@ CONTAINS a", @[@"b", @"c"]].mgl_filter;
- mbgl::style::NotInFilter expected = { .key = "a", .values = { std::string("b"), std::string("c") } };
- MGLAssertEqualFilters(actual, expected);
- }
-
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a BEGINSWITH 'L'"].mgl_filter, NSException, NSInvalidArgumentException);
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a ENDSWITH 'itude'"].mgl_filter, NSException, NSInvalidArgumentException);
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a LIKE 'glob?trotter'"].mgl_filter, NSException, NSInvalidArgumentException);
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a MATCHES 'i\\w{18}n'"].mgl_filter, NSException, NSInvalidArgumentException);
- NSPredicate *selectorPredicate = [NSPredicate predicateWithFormat:@"(SELF isKindOfClass: %@)", [MGLPolyline class]];
- XCTAssertThrowsSpecificNamed(selectorPredicate.mgl_filter, NSException, NSInvalidArgumentException);
-
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *, id> * _Nullable bindings) {
- XCTAssertTrue(NO, @"Predicate block should not be evaluated.");
- return NO;
- }].mgl_filter, NSException, NSInvalidArgumentException);
-}
-
- (void)testPredication {
XCTAssertNil([NSPredicate mgl_predicateWithFilter:mbgl::style::NullFilter()]);
-
+
{
mbgl::style::EqualsFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a = 'b'"]);
@@ -351,12 +65,12 @@ namespace mbgl {
mbgl::style::TypeEqualsFilter filter = { .value = mbgl::FeatureType::Unknown };
XCTAssertThrowsSpecificNamed([NSPredicate mgl_predicateWithFilter:filter], NSException, NSInternalInconsistencyException);
}
-
+
{
mbgl::style::NotHasFilter filter = { .key = "a" };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a = nil"]);
}
-
+
{
mbgl::style::NotEqualsFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a != 'b'"]);
@@ -379,32 +93,32 @@ namespace mbgl {
NSPredicate *expected = [NSPredicate predicateWithFormat:@"%K != nil", @"$id"];
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
}
-
+
{
mbgl::style::HasFilter filter = { .key = "a" };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a != nil"]);
}
-
+
{
mbgl::style::LessThanFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a < 'b'"]);
}
-
+
{
mbgl::style::LessThanEqualsFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a <= 'b'"]);
}
-
+
{
mbgl::style::GreaterThanFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a > 'b'"]);
}
-
+
{
mbgl::style::GreaterThanEqualsFilter filter = { .key = "a", .value = std::string("b") };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a >= 'b'"]);
}
-
+
{
mbgl::style::AllFilter filter = {
.filters = {
@@ -414,7 +128,7 @@ namespace mbgl {
};
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a BETWEEN {'b', 'z'}"]);
}
-
+
{
mbgl::style::AllFilter filter = {
.filters = {
@@ -424,7 +138,7 @@ namespace mbgl {
};
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a BETWEEN {'b', 'z'}"]);
}
-
+
{
mbgl::style::InFilter filter = { .key = "a", .values = { std::string("b"), std::string("c") } };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter].predicateFormat, [NSPredicate predicateWithFormat:@"a IN {'b', 'c'}"].predicateFormat);
@@ -441,7 +155,7 @@ namespace mbgl {
NSPredicate *expected = [NSPredicate predicateWithFormat:@"%K IN {67086180, 3709678893, 3352016856, 4189833989}", @"$id"];
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
}
-
+
{
mbgl::style::NotInFilter filter = { .key = "a", .values = { std::string("b"), std::string("c") } };
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter].predicateFormat, [NSPredicate predicateWithFormat:@"NOT a IN {'b', 'c'}"].predicateFormat);
@@ -458,12 +172,12 @@ namespace mbgl {
NSPredicate *expected = [NSPredicate predicateWithFormat:@"NOT %K IN {67086180, 3709678893, 3352016856, 4189833989}", @"$id"];
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], expected);
}
-
+
{
mbgl::style::AllFilter filter;
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithValue:YES]);
}
-
+
{
mbgl::style::AllFilter filter = {
.filters = {
@@ -473,12 +187,12 @@ namespace mbgl {
};
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a == 'b' AND c == 'd'"]);
}
-
+
{
mbgl::style::AnyFilter filter;
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithValue:NO]);
}
-
+
{
mbgl::style::AnyFilter filter = {
.filters = {
@@ -488,12 +202,12 @@ namespace mbgl {
};
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithFormat:@"a == 'b' OR c == 'd'"]);
}
-
+
{
mbgl::style::NoneFilter filter;
XCTAssertEqualObjects([NSPredicate mgl_predicateWithFilter:filter], [NSPredicate predicateWithValue:YES]);
}
-
+
{
mbgl::style::NoneFilter filter = {
.filters = {
@@ -505,76 +219,339 @@ namespace mbgl {
}
}
-- (void)testSymmetry {
- [self testSymmetryWithFormat:@"a = 1" reverseFormat:@"1 = a" mustRoundTrip:YES];
- [self testSymmetryWithFormat:@"a != 1" reverseFormat:@"1 != a" mustRoundTrip:YES];
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a = b"].mgl_filter, NSException, NSInvalidArgumentException);
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"1 = 1"].mgl_filter, NSException, NSInvalidArgumentException);
-
- // In the predicate format language, $ is a special character denoting a
- // variable. Use %K to escape the special feature attribute $id.
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"$id == 670861802"].mgl_filter, NSException, NSInvalidArgumentException);
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a = $id"].mgl_filter, NSException, NSInvalidArgumentException);
-
- [self testSymmetryWithFormat:@"a = nil" reverseFormat:@"nil = a" mustRoundTrip:YES];
- [self testSymmetryWithFormat:@"a != nil" reverseFormat:@"nil != a" mustRoundTrip:YES];
-
- [self testSymmetryWithFormat:@"a < 1" reverseFormat:@"1 > a" mustRoundTrip:YES];
- [self testSymmetryWithFormat:@"a <= 1" reverseFormat:@"1 >= a" mustRoundTrip:YES];
- [self testSymmetryWithFormat:@"a > 1" reverseFormat:@"1 < a" mustRoundTrip:YES];
- [self testSymmetryWithFormat:@"a >= 1" reverseFormat:@"1 <= a" mustRoundTrip:YES];
-
- [self testSymmetryWithFormat:@"a BETWEEN {1, 2}" reverseFormat:@"1 <= a && 2 >= a" mustRoundTrip:YES];
- [self testSymmetryWithPredicate:[NSPredicate predicateWithFormat:@"a BETWEEN %@", @[@1, @2]]
- reversePredicate:[NSPredicate predicateWithFormat:@"1 <= a && 2 >= a"]
- mustRoundTrip:YES];
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"{1, 2} BETWEEN a"].mgl_filter, NSException, NSInvalidArgumentException);
- NSPredicate *betweenSetPredicate = [NSPredicate predicateWithFormat:@"a BETWEEN %@", [NSSet setWithObjects:@1, @2, nil]];
- XCTAssertThrowsSpecificNamed(betweenSetPredicate.mgl_filter, NSException, NSInvalidArgumentException);
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a BETWEEN {1}"].mgl_filter, NSException, NSInvalidArgumentException);
- XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a BETWEEN {1, 2, 3}"].mgl_filter, NSException, NSInvalidArgumentException);
-
- [self testSymmetryWithFormat:@"a IN {1, 2}" reverseFormat:@"{1, 2} CONTAINS a" mustRoundTrip:NO];
- [self testSymmetryWithPredicate:[NSPredicate predicateWithFormat:@"a IN %@", @[@1, @2]]
- reversePredicate:[NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@1, @2]]
- mustRoundTrip:YES];
+- (void)testUnsupportedFilterPredicates {
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"1 == 2"].mgl_filter, NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"1 == 1"].mgl_filter, NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithValue:YES].mgl_filter, NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithValue:NO].mgl_filter, NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a BEGINSWITH 'L'"].mgl_filter, NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a ENDSWITH 'itude'"].mgl_filter, NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a LIKE 'glob?trotter'"].mgl_filter, NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithFormat:@"a MATCHES 'i\\w{18}n'"].mgl_filter, NSException, NSInvalidArgumentException);
+ NSPredicate *selectorPredicate = [NSPredicate predicateWithFormat:@"(SELF isKindOfClass: %@)", [MGLPolyline class]];
+ XCTAssertThrowsSpecificNamed(selectorPredicate.mgl_filter, NSException, NSInvalidArgumentException);
+
+ XCTAssertThrowsSpecificNamed([NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *, id> * _Nullable bindings) {
+ XCTAssertTrue(NO, @"Predicate block should not be evaluated.");
+ return NO;
+ }].mgl_filter, NSException, NSInvalidArgumentException);
+}
- // The reverse formats here are a bit backwards because we canonicalize
- // a reverse CONTAINS to a forward IN.
- [self testSymmetryWithFormat:@"{1, 2} CONTAINS a" reverseFormat:@"{1, 2} CONTAINS a" mustRoundTrip:NO];
- [self testSymmetryWithPredicate:[NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@1, @2]]
- reversePredicate:[NSPredicate predicateWithFormat:@"%@ CONTAINS a", @[@1, @2]]
- mustRoundTrip:NO];
+- (void)testComparisonPredicates {
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"x == YES"];
+ NSArray *jsonExpression = @[@"==", @[@"get", @"x"], @YES];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') < 5"];
+ NSArray *jsonExpression = @[@"<", @[@"to-number", @[@"get", @"x"]], @5];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') > 5"];
+ NSArray *jsonExpression = @[@">", @[@"to-number", @[@"get", @"x"]], @5];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') <= 5"];
+ NSArray *jsonExpression = @[@"<=", @[@"to-number", @[@"get", @"x"]], @5];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') >= 5"];
+ NSArray *jsonExpression = @[@">=", @[@"to-number", @[@"get", @"x"]], @5];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSString') > 'value'"];
+ NSArray *jsonExpression = @[@">", @[@"to-string", @[@"get", @"x"]], @"value"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"a = 'b'"];
+ NSArray *jsonExpression = @[@"==", @[@"get", @"a"], @"b"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"$geometryType = 'Point'"];
+ NSArray *jsonExpression = @[@"==", @[@"geometry-type"], @"Point"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 67086180"];
+ NSArray *jsonExpression = @[@"==", @[@"id"], @67086180];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = nil"];
+ NSArray *jsonExpression = @[@"==", @[@"id"], [NSNull null]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"a = nil"];
+ NSArray *jsonExpression = @[@"==", @[@"get", @"a"], [NSNull null]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"$geometryType != 'Point'"];
+ NSArray *jsonExpression = @[@"!=", @[@"geometry-type"], @"Point"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier != 67086180"];
+ NSArray *jsonExpression = @[@"!=", @[@"id"], @67086180];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier != nil"];
+ NSArray *jsonExpression = @[@"!=", @[@"id"], [NSNull null]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"a != 'b'"];
+ NSArray *jsonExpression = @[@"!=", @[@"get", @"a"], @"b"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"a != nil"];
+ NSArray *jsonExpression = @[@"!=", @[@"get", @"a"], [NSNull null]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(a, 'NSString') < 'b'"];
+ NSArray *jsonExpression = @[@"<", @[@"to-string", @[@"get", @"a"]], @"b"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(a, 'NSString') <= 'b'"];
+ NSArray *jsonExpression = @[@"<=", @[@"to-string", @[@"get", @"a"]], @"b"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(a, 'NSString') > 'b'"];
+ NSArray *jsonExpression = @[@">", @[@"to-string", @[@"get", @"a"]], @"b"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(a, 'NSString') >= 'b'"];
+ NSArray *jsonExpression = @[@">=", @[@"to-string", @[@"get", @"a"]], @"b"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(a, 'NSString') BETWEEN {'b', 'z'}"];
+ NSArray *jsonExpression =@[@"all", @[@"<=", @"b", @[@"to-string", @[@"get", @"a"]]], @[@"<=", @[@"to-string", @[@"get", @"a"]], @"z"]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSExpression *limits = [NSExpression expressionForAggregate:@[[NSExpression expressionForConstantValue:@10], [NSExpression expressionForConstantValue:@100]]];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') BETWEEN %@", limits];
+ NSArray *jsonExpression = @[@"all", @[@">=", @[@"to-number", @[@"get", @"x"]], @10], @[@"<=", @[@"to-number", @[@"get", @"x"]], @100]];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSArray *expected = @[@"all", @[@"<=", @10, @[@"to-number", @[@"get", @"x"]]], @[@"<=", @[@"to-number", @[@"get", @"x"]], @100]];
+ NSExpression *limits = [NSExpression expressionForAggregate:@[[NSExpression expressionForConstantValue:@10], [NSExpression expressionForConstantValue:@100]]];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') BETWEEN %@", limits];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:expected], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:expected]
+ mustRoundTrip:NO];
+ }
+ {
+ NSArray *expected = @[@"all", @[@"<=", @10, @[@"to-number", @[@"get", @"x"]]], @[@">=", @100, @[@"to-number", @[@"get", @"x"]]]];
+ NSExpression *limits = [NSExpression expressionForAggregate:@[[NSExpression expressionForConstantValue:@10], [NSExpression expressionForConstantValue:@100]]];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') BETWEEN %@", limits];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:expected], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:expected]
+ mustRoundTrip:NO];
+ }
+ {
+ NSArray *expected = @[@"all", @[@">=", @[@"to-number", @[@"get", @"x"]], @10], @[@">=", @100, @[@"to-number", @[@"get", @"x"]]]];
+ NSExpression *limits = [NSExpression expressionForAggregate:@[[NSExpression expressionForConstantValue:@10], [NSExpression expressionForConstantValue:@100]]];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"CAST(x, 'NSNumber') BETWEEN %@", limits];
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:expected], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:expected]
+ mustRoundTrip:NO];
+ }
+ {
+ NSArray *expected = @[@"match", @[@"id"], @6, @YES, @5, @YES, @4, @YES, @3, @YES, @NO];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier IN { 6, 5, 4, 3}"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"MGL_MATCH(CAST($featureIdentifier, 'NSNumber'), 3, YES, 4, YES, 5, YES, 6, YES, NO) == YES"];
+ auto forwardFilter = [NSPredicate mgl_predicateWithJSONObject:expected].mgl_filter;
+ NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
+ XCTAssertEqualObjects(predicateAfter, forwardPredicateAfter);
+ }
+ {
+ NSArray *expected = @[@"!", @[@"match", @[@"get", @"x"], @6, @YES, @5, @YES, @4, @YES, @3, @YES, @NO]];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT x IN { 6, 5, 4, 3}"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"NOT MGL_MATCH(CAST(x, 'NSNumber'), 3, YES, 4, YES, 5, YES, 6, YES, NO) == YES"];
+ auto forwardFilter = [NSPredicate mgl_predicateWithJSONObject:expected].mgl_filter;
+ NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
+ XCTAssertEqualObjects(predicateAfter, forwardPredicateAfter);
+ }
+ {
+ NSArray *expected = @[@"match", @[@"get", @"a"], @"b", @YES, @"c", @YES, @NO];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"a IN { 'b', 'c' }"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"MGL_MATCH(CAST(a, 'NSString'), 'b', YES, 'c', YES, NO) == YES"];
+ auto forwardFilter = [NSPredicate mgl_predicateWithJSONObject:expected].mgl_filter;
+ NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
+ XCTAssertEqualObjects(predicateAfter, forwardPredicateAfter);
+ }
+ {
+ NSArray *expected = @[@"match", @[@"geometry-type"], @"LineString", @YES, @"Polygon", @YES, @NO];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%@ IN %@", [NSExpression expressionForVariable:@"geometryType"], @[@"LineString", @"Polygon"]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"MGL_MATCH($geometryType, 'LineString', YES, 'Polygon', YES, NO) == YES"];
+ auto forwardFilter = [NSPredicate mgl_predicateWithJSONObject:expected].mgl_filter;
+ NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
+ XCTAssertEqualObjects(predicateAfter, forwardPredicateAfter);
+ }
+ {
+ NSArray *expected = @[@"match", @[@"get", @"x"], @6, @YES, @5, @YES, @4, @YES, @3, @YES, @NO];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"{ 6, 5, 4, 3} CONTAINS x"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"MGL_MATCH(CAST(x, 'NSNumber'), 3, YES, 4, YES, 5, YES, 6, YES, NO) == YES"];
+ auto forwardFilter = [NSPredicate mgl_predicateWithJSONObject:expected].mgl_filter;
+ NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
+ XCTAssertEqualObjects(predicateAfter, forwardPredicateAfter);
+ }
+ {
+ NSArray *expected = @[@"match", @[@"geometry-type"], @"LineString", @YES, @"Polygon", @YES, @NO];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%@ CONTAINS %@", @[@"LineString", @"Polygon"], [NSExpression expressionForVariable:@"geometryType"]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"MGL_MATCH($geometryType, 'LineString', YES, 'Polygon', YES, NO) == YES"];
+ auto forwardFilter = [NSPredicate mgl_predicateWithJSONObject:expected].mgl_filter;
+ NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
+ XCTAssertEqualObjects(predicateAfter, forwardPredicateAfter);
+ }
+ {
+ NSArray *expected = @[@"match", @[@"id"], @6, @YES, @5, @YES, @4, @YES, @3, @YES, @NO];
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"{ 6, 5, 4, 3} CONTAINS $featureIdentifier"];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, expected);
+ NSPredicate *predicateAfter = [NSPredicate predicateWithFormat:@"MGL_MATCH(CAST($featureIdentifier, 'NSNumber'), 3, YES, 4, YES, 5, YES, 6, YES, NO) == YES"];
+ auto forwardFilter = [NSPredicate mgl_predicateWithJSONObject:expected].mgl_filter;
+ NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
+ XCTAssertEqualObjects(predicateAfter, forwardPredicateAfter);
+ }
}
-- (void)testSymmetryWithFormat:(NSString *)forwardFormat reverseFormat:(NSString *)reverseFormat mustRoundTrip:(BOOL)mustRoundTrip {
- NSPredicate *forwardPredicate = [NSPredicate predicateWithFormat:forwardFormat];
- NSPredicate *reversePredicate = reverseFormat ? [NSPredicate predicateWithFormat:reverseFormat] : nil;
- [self testSymmetryWithPredicate:forwardPredicate reversePredicate:reversePredicate mustRoundTrip:mustRoundTrip];
+- (void)testCompoundPredicates {
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"a == 'b' AND c == 'd'"];
+ NSArray *jsonExpression = @[@"all", @[@"==", @[@"get", @"a"], @"b"], @[@"==", @[@"get", @"c"], @"d"]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"a == 'b' OR c == 'd'"];
+ NSArray *jsonExpression = @[@"any", @[@"==", @[@"get", @"a"], @"b"], @[@"==", @[@"get", @"c"], @"d"]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT(a == 'b' AND c == 'd')"];
+ NSArray *jsonExpression = @[@"!", @[@"all", @[@"==", @[@"get", @"a"], @"b"], @[@"==", @[@"get", @"c"], @"d"]]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT(a == 'b' OR c == 'd')"];
+ NSArray *jsonExpression = @[@"!", @[@"any", @[@"==", @[@"get", @"a"], @"b"], @[@"==", @[@"get", @"c"], @"d"]]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ XCTAssertEqualObjects([NSPredicate mgl_predicateWithJSONObject:jsonExpression], predicate);
+ [self testSymmetryWithPredicate:[NSPredicate mgl_predicateWithJSONObject:jsonExpression]
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT a == nil"];
+ NSArray *jsonExpression = @[@"!", @[@"==", @[@"get", @"a"], [NSNull null]]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
+ {
+ NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT a != nil"];
+ NSArray *jsonExpression = @[@"!", @[@"!=", @[@"get", @"a"], [NSNull null]]];
+ XCTAssertEqualObjects(predicate.mgl_jsonExpressionObject, jsonExpression);
+ [self testSymmetryWithPredicate:predicate
+ mustRoundTrip:NO];
+ }
}
-- (void)testSymmetryWithPredicate:(NSPredicate *)forwardPredicate reversePredicate:(NSPredicate *)reversePredicate mustRoundTrip:(BOOL)mustRoundTrip {
+- (void)testSymmetryWithPredicate:(NSPredicate *)forwardPredicate mustRoundTrip:(BOOL)mustRoundTrip {
auto forwardFilter = forwardPredicate.mgl_filter;
NSPredicate *forwardPredicateAfter = [NSPredicate mgl_predicateWithFilter:forwardFilter];
if (mustRoundTrip) {
// A collection of ints may turn into an aggregate of longs, for
// example, so compare formats instead of the predicates themselves.
XCTAssertEqualObjects(forwardPredicate.predicateFormat, forwardPredicateAfter.predicateFormat);
- }
-
- if (reversePredicate) {
- auto reverseFilter = reversePredicate.mgl_filter;
- NSPredicate *reversePredicateAfter = [NSPredicate mgl_predicateWithFilter:reverseFilter];
- XCTAssertNotEqualObjects(reversePredicate, reversePredicateAfter);
-
- XCTAssertEqualObjects(forwardPredicateAfter, reversePredicateAfter);
- }
-}
-
-- (void)testComparisonExpressionArray {
- {
- NSArray *expected = @[@"==", @1, @2];
- XCTAssertEqualObjects([NSPredicate predicateWithFormat:@"1 = 2"].mgl_jsonExpressionObject, expected);
+ } else {
+ XCTAssertEqualObjects(forwardPredicate, forwardPredicateAfter);
}
}
diff --git a/platform/darwin/test/MGLRasterStyleLayerTests.mm b/platform/darwin/test/MGLRasterStyleLayerTests.mm
index 5ded23ee3c..c8e454743e 100644
--- a/platform/darwin/test/MGLRasterStyleLayerTests.mm
+++ b/platform/darwin/test/MGLRasterStyleLayerTests.mm
@@ -45,7 +45,7 @@
@"maximumRasterBrightness should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.maximumRasterBrightness = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -69,8 +69,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.maximumRasterBrightness = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.maximumRasterBrightness = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -89,7 +89,7 @@
@"minimumRasterBrightness should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.minimumRasterBrightness = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -113,8 +113,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.minimumRasterBrightness = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.minimumRasterBrightness = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -133,7 +133,7 @@
@"rasterContrast should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.rasterContrast = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -157,8 +157,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.rasterContrast = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.rasterContrast = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.rasterContrastTransition = transitionTest;
@@ -186,7 +186,7 @@
@"rasterFadeDuration should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.rasterFadeDuration = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -210,8 +210,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.rasterFadeDuration = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.rasterFadeDuration = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -230,7 +230,7 @@
@"rasterHueRotation should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.rasterHueRotation = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -254,8 +254,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.rasterHueRotation = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.rasterHueRotation = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -274,7 +274,7 @@
@"rasterOpacity should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.rasterOpacity = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -298,8 +298,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.rasterOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.rasterOpacity = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.rasterOpacityTransition = transitionTest;
@@ -327,7 +327,7 @@
@"rasterSaturation should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.rasterSaturation = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -351,8 +351,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.rasterSaturation = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.rasterSaturation = functionExpression, NSException, NSInvalidArgumentException, @"MGLRasterLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
// Transition property test
layer.rasterSaturationTransition = transitionTest;
diff --git a/platform/darwin/test/MGLSDKTestHelpers.swift b/platform/darwin/test/MGLSDKTestHelpers.swift
index 576e3da86b..727d8bf0c6 100644
--- a/platform/darwin/test/MGLSDKTestHelpers.swift
+++ b/platform/darwin/test/MGLSDKTestHelpers.swift
@@ -23,9 +23,9 @@ extension MGLSDKTestHelpers {
class func protocolMethodDescriptions(_ p: Protocol) -> Set<String> {
var methods = Set<String>()
var methodCount = UInt32()
- let methodDescriptionList: UnsafeMutablePointer<objc_method_description>! = protocol_copyMethodDescriptionList(p, false, true, &methodCount)
+ let methodDescriptionList = protocol_copyMethodDescriptionList(p, false, true, &methodCount)
for i in 0..<Int(methodCount) {
- let description: objc_method_description = methodDescriptionList[i]
+ let description = methodDescriptionList![i]
XCTAssertNotNil(description.name?.description)
methods.insert(description.name!.description)
}
@@ -36,11 +36,16 @@ extension MGLSDKTestHelpers {
class func classMethodDescriptions(_ cls: Swift.AnyClass) -> Set<String> {
var methods = Set<String>()
var methodCount = UInt32()
- let methodList: UnsafeMutablePointer<Method?>! = class_copyMethodList(cls, &methodCount)
+ let methodList = class_copyMethodList(cls, &methodCount)
for i in 0..<Int(methodCount) {
- let method = methodList[i]
- let selector : Selector = method_getName(method)
- methods.insert(selector.description)
+ let method = methodList![i]
+ let selector = method_getName(method)
+ #if os(macOS)
+ methods.insert(selector.description)
+ #else
+ XCTAssertNotNil(selector)
+ methods.insert(selector!.description)
+ #endif
}
free(methodList)
return methods
diff --git a/platform/darwin/test/MGLShapeSourceTests.mm b/platform/darwin/test/MGLShapeSourceTests.mm
index 868dca730a..d3f9a599e2 100644
--- a/platform/darwin/test/MGLShapeSourceTests.mm
+++ b/platform/darwin/test/MGLShapeSourceTests.mm
@@ -2,7 +2,6 @@
#import <Mapbox/Mapbox.h>
#import "MGLFeature_Private.h"
-#import "MGLAbstractShapeSource_Private.h"
#import "MGLShapeSource_Private.h"
#import "MGLSource_Private.h"
diff --git a/platform/darwin/test/MGLSourceQueryTests.m b/platform/darwin/test/MGLSourceQueryTests.m
index d1ef180a52..b321da1ea4 100644
--- a/platform/darwin/test/MGLSourceQueryTests.m
+++ b/platform/darwin/test/MGLSourceQueryTests.m
@@ -7,8 +7,8 @@
@implementation MGLSourceQueryTests
-- (void) testQueryVectorSource {
- MGLVectorSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"vector" tileURLTemplates:@[@"fake"] options:nil];
+- (void) testQueryVectorTileSource {
+ MGLVectorTileSource *source = [[MGLVectorTileSource alloc] initWithIdentifier:@"vector" tileURLTemplates:@[@"fake"] options:nil];
NSSet *sourceLayers = [NSSet setWithObjects:@"buildings", @"water", nil];
NSArray* features = [source featuresInSourceLayersWithIdentifiers:sourceLayers predicate:nil];
// Source not added yet, so features is 0
diff --git a/platform/darwin/test/MGLStyleLayerTests.mm.ejs b/platform/darwin/test/MGLStyleLayerTests.mm.ejs
index e17501ed18..f70f0bba23 100644
--- a/platform/darwin/test/MGLStyleLayerTests.mm.ejs
+++ b/platform/darwin/test/MGLStyleLayerTests.mm.ejs
@@ -36,8 +36,8 @@
XCTAssertNil(layer.sourceLayerIdentifier);
XCTAssertNil(layer.predicate);
- layer.predicate = [NSPredicate predicateWithValue:NO];
- XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
+ layer.predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"]);
layer.predicate = nil;
XCTAssertNil(layer.predicate);
}
@@ -80,7 +80,7 @@
@"<%- objCName(property) %> should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:<%- objCTestValue(property, type, false, 3) %>];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.<%- objCName(property) %> = functionExpression;
mbgl::style::IntervalStops<<%- mbglType(property) %>> intervalStops = {{
@@ -95,7 +95,7 @@
@"<%- objCName(property) %> should round-trip camera expressions.");
<% if (property["property-function"] && isInterpolatable(property)) { -%>
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.<%- objCName(property) %> = functionExpression;
mbgl::style::ExponentialStops<<%- mbglType(property) %>> exponentialStops = { {{18, <%- mbglTestValue(property, type) %>}}, 1.0 };
@@ -103,10 +103,11 @@
XCTAssertEqual(rawLayer->get<%- camelize(originalPropertyName(property)) %>(), propertyValue,
@"Setting <%- objCName(property) %> to a data expression should update <%- originalPropertyName(property) %>.");
- XCTAssertEqualObjects(layer.<%- objCName(property) %>, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.<%- objCName(property) %>, pedanticFunctionExpression,
@"<%- objCName(property) %> should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.<%- objCName(property) %> = functionExpression;
std::map<float, <%- mbglType(property) %>> innerStops { {18, <%- mbglTestValue(property, type) %>} };
@@ -116,7 +117,8 @@
XCTAssertEqual(rawLayer->get<%- camelize(originalPropertyName(property)) %>(), propertyValue,
@"Setting <%- objCName(property) %> to a camera-data expression should update <%- originalPropertyName(property) %>.");
- XCTAssertEqualObjects(layer.<%- objCName(property) %>, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.<%- objCName(property) %>, pedanticFunctionExpression,
@"<%- objCName(property) %> should round-trip camera-data expressions.");
<% } -%>
<% if (!property.required) { -%>
@@ -131,8 +133,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.<%- objCName(property) %> = functionExpression, NSException, NSInvalidArgumentException, @"MGL<%- camelize(type) %>Layer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.<%- objCName(property) %> = functionExpression, NSException, NSInvalidArgumentException, @"MGL<%- camelize(type) %>Layer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
<% } -%>
<% if (property["transition"] && !property.original) { -%>
diff --git a/platform/darwin/test/MGLStyleTests.mm b/platform/darwin/test/MGLStyleTests.mm
index 8f610e338c..6048f39ea3 100644
--- a/platform/darwin/test/MGLStyleTests.mm
+++ b/platform/darwin/test/MGLStyleTests.mm
@@ -1,6 +1,7 @@
#import <Mapbox/Mapbox.h>
#import "NSBundle+MGLAdditions.h"
+#import "MGLVectorTileSource_Private.h"
#import <mbgl/util/default_styles.hpp>
@@ -64,12 +65,6 @@
XCTAssertEqualObjects([MGLStyle darkStyleURL].absoluteString, @(mbgl::util::default_styles::dark.url));
XCTAssertEqualObjects([MGLStyle satelliteStyleURL].absoluteString, @(mbgl::util::default_styles::satellite.url));
XCTAssertEqualObjects([MGLStyle satelliteStreetsStyleURL].absoluteString, @(mbgl::util::default_styles::satelliteStreets.url));
-
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- XCTAssertEqualObjects([MGLStyle emeraldStyleURL].absoluteString, @"mapbox://styles/mapbox/emerald-v8");
- XCTAssertEqualObjects([MGLStyle hybridStyleURL].absoluteString, @"mapbox://styles/mapbox/satellite-hybrid-v8");
-#pragma clang diagnostic pop
}
- (void)testVersionedStyleURLs {
@@ -99,19 +94,8 @@
@(mbgl::util::default_styles::satelliteStreets.url));
XCTAssertEqualObjects([MGLStyle satelliteStreetsStyleURLWithVersion:99].absoluteString,
@"mapbox://styles/mapbox/satellite-streets-v99");
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- XCTAssertEqualObjects([MGLStyle trafficDayStyleURLWithVersion:mbgl::util::default_styles::trafficDay.currentVersion].absoluteString,
- @(mbgl::util::default_styles::trafficDay.url));
- XCTAssertEqualObjects([MGLStyle trafficDayStyleURLWithVersion:99].absoluteString,
- @"mapbox://styles/mapbox/traffic-day-v99");
- XCTAssertEqualObjects([MGLStyle trafficNightStyleURLWithVersion:mbgl::util::default_styles::trafficNight.currentVersion].absoluteString,
- @(mbgl::util::default_styles::trafficNight.url));
- XCTAssertEqualObjects([MGLStyle trafficNightStyleURLWithVersion:99].absoluteString,
- @"mapbox://styles/mapbox/traffic-night-v99");
-#pragma clang diagnostic pop
-
- static_assert(8 == mbgl::util::default_styles::numOrderedStyles,
+
+ static_assert(6 == mbgl::util::default_styles::numOrderedStyles,
"MGLStyleTests isn’t testing all the styles in mbgl::util::default_styles.");
}
@@ -143,7 +127,7 @@
NSString *styleHeader = self.stringWithContentsOfStyleHeader;
NSError *versionedMethodError;
- NSString *versionedMethodExpressionString = @(R"RE(^\+\s*\(NSURL\s*\*\s*\)\s*\w+StyleURLWithVersion\s*:\s*\(\s*NSInteger\s*\)\s*version\s*\b)RE");
+ NSString *versionedMethodExpressionString = @(R"RE(^\+\s*\(NSURL\s*\*\s*\)\s*(?!traffic)\w+StyleURLWithVersion\s*:\s*\(\s*NSInteger\s*\)\s*version\s*\b)RE");
NSRegularExpression *versionedMethodExpression = [NSRegularExpression regularExpressionWithPattern:versionedMethodExpressionString options:NSRegularExpressionAnchorsMatchLines error:&versionedMethodError];
XCTAssertNil(versionedMethodError, @"Error compiling regular expression to search for versioned methods.");
NSUInteger numVersionedMethodDeclarations = [versionedMethodExpression numberOfMatchesInString:styleHeader options:0 range:NSMakeRange(0, styleHeader.length)];
@@ -174,89 +158,89 @@
[self.style addSource:shapeSource];
XCTAssertThrowsSpecificNamed([self.style addSource:shapeSource], NSException, @"MGLRedundantSourceException");
- MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"rasterSource" configurationURL:[NSURL URLWithString:@".json"] tileSize:42];
- [self.style addSource:rasterSource];
- XCTAssertThrowsSpecificNamed([self.style addSource:rasterSource], NSException, @"MGLRedundantSourceException");
+ MGLRasterTileSource *rasterTileSource = [[MGLRasterTileSource alloc] initWithIdentifier:@"rasterTileSource" configurationURL:[NSURL URLWithString:@".json"] tileSize:42];
+ [self.style addSource:rasterTileSource];
+ XCTAssertThrowsSpecificNamed([self.style addSource:rasterTileSource], NSException, @"MGLRedundantSourceException");
- MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"vectorSource" configurationURL:[NSURL URLWithString:@".json"]];
- [self.style addSource:vectorSource];
- XCTAssertThrowsSpecificNamed([self.style addSource:vectorSource], NSException, @"MGLRedundantSourceException");
+ MGLVectorTileSource *vectorTileSource = [[MGLVectorTileSource alloc] initWithIdentifier:@"vectorTileSource" configurationURL:[NSURL URLWithString:@".json"]];
+ [self.style addSource:vectorTileSource];
+ XCTAssertThrowsSpecificNamed([self.style addSource:vectorTileSource], NSException, @"MGLRedundantSourceException");
}
- (void)testAddingSourcesWithDuplicateIdentifiers {
- MGLVectorSource *source1 = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
- MGLVectorSource *source2 = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
+ MGLVectorTileSource *source1 = [[MGLVectorTileSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
+ MGLVectorTileSource *source2 = [[MGLVectorTileSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
[self.style addSource: source1];
XCTAssertThrowsSpecificNamed([self.style addSource: source2], NSException, @"MGLRedundantSourceIdentifierException");
}
- (void)testRemovingSourcesBeforeAddingThem {
- MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"raster-source" tileURLTemplates:@[] options:nil];
- [self.style removeSource:rasterSource];
- [self.style addSource:rasterSource];
- XCTAssertNotNil([self.style sourceWithIdentifier:rasterSource.identifier]);
+ MGLRasterTileSource *rasterTileSource = [[MGLRasterTileSource alloc] initWithIdentifier:@"raster-tile-source" tileURLTemplates:@[] options:nil];
+ [self.style removeSource:rasterTileSource];
+ [self.style addSource:rasterTileSource];
+ XCTAssertNotNil([self.style sourceWithIdentifier:rasterTileSource.identifier]);
MGLShapeSource *shapeSource = [[MGLShapeSource alloc] initWithIdentifier:@"shape-source" shape:nil options:nil];
[self.style removeSource:shapeSource];
[self.style addSource:shapeSource];
XCTAssertNotNil([self.style sourceWithIdentifier:shapeSource.identifier]);
- MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"vector-source" tileURLTemplates:@[] options:nil];
- [self.style removeSource:vectorSource];
- [self.style addSource:vectorSource];
- XCTAssertNotNil([self.style sourceWithIdentifier:vectorSource.identifier]);
+ MGLVectorTileSource *vectorTileSource = [[MGLVectorTileSource alloc] initWithIdentifier:@"vector-tile-source" tileURLTemplates:@[] options:nil];
+ [self.style removeSource:vectorTileSource];
+ [self.style addSource:vectorTileSource];
+ XCTAssertNotNil([self.style sourceWithIdentifier:vectorTileSource.identifier]);
}
- (void)testAddingSourceOfTypeABeforeSourceOfTypeBWithSameIdentifier {
- // Add a raster source
- MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil];
- [self.style addSource:rasterSource];
+ // Add a raster tile source
+ MGLRasterTileSource *rasterTileSource = [[MGLRasterTileSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil];
+ [self.style addSource:rasterTileSource];
- // Attempt to remove an image source with the same identifier as the raster source
+ // Attempt to remove an image source with the same identifier as the raster tile source
MGLImageSource *imageSource = [[MGLImageSource alloc] initWithIdentifier:@"some-identifier" coordinateQuad: { } URL:[NSURL URLWithString:@"http://host/image.png"]];
[self.style removeSource:imageSource];
- // The raster source should still be added
- XCTAssertTrue([[self.style sourceWithIdentifier:rasterSource.identifier] isMemberOfClass:[MGLRasterSource class]]);
+ // The raster tile source should still be added
+ XCTAssertTrue([[self.style sourceWithIdentifier:rasterTileSource.identifier] isMemberOfClass:[MGLRasterTileSource class]]);
- // Remove the raster source
- [self.style removeSource:rasterSource];
+ // Remove the raster tile source
+ [self.style removeSource:rasterTileSource];
// Add the shape source
[self.style addSource:imageSource];
- // Attempt to remove a vector source with the same identifer as the shape source
- MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil];
- [self.style removeSource:vectorSource];
+ // Attempt to remove a vector tile source with the same identifer as the shape source
+ MGLVectorTileSource *vectorTileSource = [[MGLVectorTileSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil];
+ [self.style removeSource:vectorTileSource];
// The image source should still be added
XCTAssertTrue([[self.style sourceWithIdentifier:imageSource.identifier] isMemberOfClass:[MGLImageSource class]]);
// Remove the image source
[self.style removeSource:imageSource];
- // Add the vector source
- [self.style addSource:vectorSource];
+ // Add the vector tile source
+ [self.style addSource:vectorTileSource];
- // Attempt to remove the previously created raster source that has the same identifer as the shape source
- [self.style removeSource:rasterSource];
- // The vector source should still be added
- XCTAssertTrue([[self.style sourceWithIdentifier:imageSource.identifier] isMemberOfClass:[MGLVectorSource class]]);
+ // Attempt to remove the previously created raster tile source that has the same identifer as the shape source
+ [self.style removeSource:rasterTileSource];
+ // The vector tile source should still be added
+ XCTAssertTrue([[self.style sourceWithIdentifier:imageSource.identifier] isMemberOfClass:[MGLVectorTileSource class]]);
}
- (void)testRemovingSourceInUse {
- // Add a raster source
- MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil];
- [self.style addSource:rasterSource];
+ // Add a raster tile source
+ MGLRasterTileSource *rasterTileSource = [[MGLRasterTileSource alloc] initWithIdentifier:@"some-identifier" tileURLTemplates:@[] options:nil];
+ [self.style addSource:rasterTileSource];
// Add a layer using it
- MGLFillStyleLayer *fillLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"fillLayer" source:rasterSource];
+ MGLFillStyleLayer *fillLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"fillLayer" source:rasterTileSource];
[self.style addLayer:fillLayer];
- // Attempt to remove the raster source
- [self.style removeSource:rasterSource];
+ // Attempt to remove the raster tile source
+ [self.style removeSource:rasterTileSource];
// Ensure it is still there
- XCTAssertTrue([[self.style sourceWithIdentifier:rasterSource.identifier] isMemberOfClass:[MGLRasterSource class]]);
+ XCTAssertTrue([[self.style sourceWithIdentifier:rasterTileSource.identifier] isMemberOfClass:[MGLRasterTileSource class]]);
}
- (void)testLayers {
@@ -306,7 +290,7 @@
- (void)testAddingLayersWithDuplicateIdentifiers {
// Just some source
- MGLVectorSource *source = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
+ MGLVectorTileSource *source = [[MGLVectorTileSource alloc] initWithIdentifier:@"my-source" configurationURL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
[self.style addSource: source];
// Add initial layer
@@ -383,13 +367,6 @@
return styleHeader;
}
-- (void)testClasses {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdeprecated-declarations"
- XCTAssertEqual(self.style.styleClasses.count, 0);
-#pragma clang diagnostic pop
-}
-
- (void)testImages {
NSString *imageName = @"TrackingLocationMask";
#if TARGET_OS_IPHONE
@@ -443,4 +420,45 @@
XCTAssertEqualObjects(layers[startIndex++].identifier, layer4.identifier);
}
+#pragma mark Localization tests
+
+- (void)testLanguageMatching {
+ {
+ NSArray *preferences = @[@"en"];
+ XCTAssertEqualObjects([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences], @"en");
+ }
+ {
+ NSArray *preferences = @[@"en-US"];
+ XCTAssertEqualObjects([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences], @"en");
+ }
+ {
+ NSArray *preferences = @[@"fr"];
+ XCTAssertEqualObjects([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences], @"fr");
+ }
+ {
+ NSArray *preferences = @[@"zh-Hans"];
+ XCTAssertEqualObjects([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences], @"zh-Hans");
+ }
+ {
+ NSArray *preferences = @[@"zh-Hans", @"en"];
+ XCTAssertEqualObjects([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences], @"zh-Hans");
+ }
+ {
+ NSArray *preferences = @[@"zh-Hant"];
+ XCTAssertNil([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences]);
+ }
+ {
+ NSArray *preferences = @[@"tlh"];
+ XCTAssertNil([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences]);
+ }
+ {
+ NSArray *preferences = @[@"tlh", @"en"];
+ XCTAssertEqualObjects([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences], @"en");
+ }
+ {
+ NSArray *preferences = @[@"mul"];
+ XCTAssertNil([MGLVectorTileSource preferredMapboxStreetsLanguageForPreferences:preferences]);
+ }
+}
+
@end
diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.mm b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
index 05e091b5c8..cf2f80125a 100644
--- a/platform/darwin/test/MGLSymbolStyleLayerTests.mm
+++ b/platform/darwin/test/MGLSymbolStyleLayerTests.mm
@@ -30,8 +30,8 @@
XCTAssertNil(layer.sourceLayerIdentifier);
XCTAssertNil(layer.predicate);
- layer.predicate = [NSPredicate predicateWithValue:NO];
- XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithValue:NO]);
+ layer.predicate = [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"];
+ XCTAssertEqualObjects(layer.predicate, [NSPredicate predicateWithFormat:@"$featureIdentifier = 1"]);
layer.predicate = nil;
XCTAssertNil(layer.predicate);
}
@@ -63,7 +63,7 @@
@"iconAllowsOverlap should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"true"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconAllowsOverlap = functionExpression;
mbgl::style::IntervalStops<bool> intervalStops = {{
@@ -87,8 +87,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.iconAllowsOverlap = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.iconAllowsOverlap = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -107,7 +107,7 @@
@"iconAnchor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'bottom-right'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconAnchor = functionExpression;
mbgl::style::IntervalStops<mbgl::style::SymbolAnchorType> intervalStops = {{
@@ -145,7 +145,7 @@
@"iconIgnoresPlacement should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"true"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconIgnoresPlacement = functionExpression;
mbgl::style::IntervalStops<bool> intervalStops = {{
@@ -169,8 +169,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.iconIgnoresPlacement = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.iconIgnoresPlacement = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -189,7 +189,7 @@
@"iconImageName should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'Icon Image'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconImageName = functionExpression;
mbgl::style::IntervalStops<std::string> intervalStops = {{
@@ -233,7 +233,7 @@
@"iconOffset should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconOffset = functionExpression;
mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
@@ -247,7 +247,7 @@
XCTAssertEqualObjects(layer.iconOffset, functionExpression,
@"iconOffset should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.iconOffset = functionExpression;
mbgl::style::ExponentialStops<std::array<float, 2>> exponentialStops = { {{18, { 1, 1 }}}, 1.0 };
@@ -255,10 +255,11 @@
XCTAssertEqual(rawLayer->getIconOffset(), propertyValue,
@"Setting iconOffset to a data expression should update icon-offset.");
- XCTAssertEqualObjects(layer.iconOffset, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconOffset, pedanticFunctionExpression,
@"iconOffset should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.iconOffset = functionExpression;
std::map<float, std::array<float, 2>> innerStops { {18, { 1, 1 }} };
@@ -268,7 +269,8 @@
XCTAssertEqual(rawLayer->getIconOffset(), propertyValue,
@"Setting iconOffset to a camera-data expression should update icon-offset.");
- XCTAssertEqualObjects(layer.iconOffset, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconOffset, pedanticFunctionExpression,
@"iconOffset should round-trip camera-data expressions.");
@@ -294,7 +296,7 @@
@"iconOptional should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"true"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconOptional = functionExpression;
mbgl::style::IntervalStops<bool> intervalStops = {{
@@ -318,8 +320,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.iconOptional = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.iconOptional = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -338,7 +340,7 @@
@"iconPadding should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconPadding = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -362,8 +364,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.iconPadding = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.iconPadding = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -382,7 +384,7 @@
@"iconPitchAlignment should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'auto'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconPitchAlignment = functionExpression;
mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = {{
@@ -406,8 +408,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.iconPitchAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.iconPitchAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -426,7 +428,7 @@
@"iconRotation should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconRotation = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -440,7 +442,7 @@
XCTAssertEqualObjects(layer.iconRotation, functionExpression,
@"iconRotation should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.iconRotation = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -448,10 +450,11 @@
XCTAssertEqual(rawLayer->getIconRotate(), propertyValue,
@"Setting iconRotation to a data expression should update icon-rotate.");
- XCTAssertEqualObjects(layer.iconRotation, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconRotation, pedanticFunctionExpression,
@"iconRotation should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.iconRotation = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -461,7 +464,8 @@
XCTAssertEqual(rawLayer->getIconRotate(), propertyValue,
@"Setting iconRotation to a camera-data expression should update icon-rotate.");
- XCTAssertEqualObjects(layer.iconRotation, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconRotation, pedanticFunctionExpression,
@"iconRotation should round-trip camera-data expressions.");
@@ -487,7 +491,7 @@
@"iconRotationAlignment should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'auto'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconRotationAlignment = functionExpression;
mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = {{
@@ -511,8 +515,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.iconRotationAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.iconRotationAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -531,7 +535,7 @@
@"iconScale should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconScale = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -545,7 +549,7 @@
XCTAssertEqualObjects(layer.iconScale, functionExpression,
@"iconScale should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.iconScale = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -553,10 +557,11 @@
XCTAssertEqual(rawLayer->getIconSize(), propertyValue,
@"Setting iconScale to a data expression should update icon-size.");
- XCTAssertEqualObjects(layer.iconScale, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconScale, pedanticFunctionExpression,
@"iconScale should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.iconScale = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -566,7 +571,8 @@
XCTAssertEqual(rawLayer->getIconSize(), propertyValue,
@"Setting iconScale to a camera-data expression should update icon-size.");
- XCTAssertEqualObjects(layer.iconScale, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconScale, pedanticFunctionExpression,
@"iconScale should round-trip camera-data expressions.");
@@ -592,7 +598,7 @@
@"iconTextFit should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'both'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconTextFit = functionExpression;
mbgl::style::IntervalStops<mbgl::style::IconTextFitType> intervalStops = {{
@@ -616,8 +622,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.iconTextFit = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.iconTextFit = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -642,7 +648,7 @@
@"iconTextFitPadding should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"{1, 1, 1, 1}"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconTextFitPadding = functionExpression;
mbgl::style::IntervalStops<std::array<float, 4>> intervalStops = {{
@@ -666,8 +672,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.iconTextFitPadding = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.iconTextFitPadding = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -686,7 +692,7 @@
@"keepsIconUpright should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"true"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.keepsIconUpright = functionExpression;
mbgl::style::IntervalStops<bool> intervalStops = {{
@@ -710,8 +716,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.keepsIconUpright = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.keepsIconUpright = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -730,7 +736,7 @@
@"keepsTextUpright should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"false"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.keepsTextUpright = functionExpression;
mbgl::style::IntervalStops<bool> intervalStops = {{
@@ -754,8 +760,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.keepsTextUpright = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.keepsTextUpright = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -774,7 +780,7 @@
@"maximumTextAngle should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.maximumTextAngle = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -798,8 +804,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.maximumTextAngle = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.maximumTextAngle = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -818,7 +824,7 @@
@"maximumTextWidth should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.maximumTextWidth = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -832,7 +838,7 @@
XCTAssertEqualObjects(layer.maximumTextWidth, functionExpression,
@"maximumTextWidth should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.maximumTextWidth = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -840,10 +846,11 @@
XCTAssertEqual(rawLayer->getTextMaxWidth(), propertyValue,
@"Setting maximumTextWidth to a data expression should update text-max-width.");
- XCTAssertEqualObjects(layer.maximumTextWidth, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.maximumTextWidth, pedanticFunctionExpression,
@"maximumTextWidth should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.maximumTextWidth = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -853,7 +860,8 @@
XCTAssertEqual(rawLayer->getTextMaxWidth(), propertyValue,
@"Setting maximumTextWidth to a camera-data expression should update text-max-width.");
- XCTAssertEqualObjects(layer.maximumTextWidth, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.maximumTextWidth, pedanticFunctionExpression,
@"maximumTextWidth should round-trip camera-data expressions.");
@@ -879,7 +887,7 @@
@"symbolAvoidsEdges should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"true"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.symbolAvoidsEdges = functionExpression;
mbgl::style::IntervalStops<bool> intervalStops = {{
@@ -903,8 +911,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.symbolAvoidsEdges = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.symbolAvoidsEdges = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -923,7 +931,7 @@
@"symbolPlacement should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'line'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.symbolPlacement = functionExpression;
mbgl::style::IntervalStops<mbgl::style::SymbolPlacementType> intervalStops = {{
@@ -947,8 +955,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.symbolPlacement = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.symbolPlacement = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -967,7 +975,7 @@
@"symbolSpacing should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.symbolSpacing = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -991,8 +999,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.symbolSpacing = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.symbolSpacing = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -1011,7 +1019,7 @@
@"text should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'Text Field'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.text = functionExpression;
mbgl::style::IntervalStops<std::string> intervalStops = {{
@@ -1049,7 +1057,7 @@
@"textAllowsOverlap should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"true"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textAllowsOverlap = functionExpression;
mbgl::style::IntervalStops<bool> intervalStops = {{
@@ -1073,8 +1081,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.textAllowsOverlap = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.textAllowsOverlap = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -1093,7 +1101,7 @@
@"textAnchor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'bottom-right'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textAnchor = functionExpression;
mbgl::style::IntervalStops<mbgl::style::SymbolAnchorType> intervalStops = {{
@@ -1131,7 +1139,7 @@
@"textFontNames should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"{'Text Font', 'Tnof Txet'}"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textFontNames = functionExpression;
mbgl::style::IntervalStops<std::vector<std::string>> intervalStops = {{
@@ -1169,7 +1177,7 @@
@"textFontSize should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textFontSize = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -1183,7 +1191,7 @@
XCTAssertEqualObjects(layer.textFontSize, functionExpression,
@"textFontSize should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.textFontSize = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -1191,10 +1199,11 @@
XCTAssertEqual(rawLayer->getTextSize(), propertyValue,
@"Setting textFontSize to a data expression should update text-size.");
- XCTAssertEqualObjects(layer.textFontSize, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textFontSize, pedanticFunctionExpression,
@"textFontSize should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.textFontSize = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -1204,7 +1213,8 @@
XCTAssertEqual(rawLayer->getTextSize(), propertyValue,
@"Setting textFontSize to a camera-data expression should update text-size.");
- XCTAssertEqualObjects(layer.textFontSize, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textFontSize, pedanticFunctionExpression,
@"textFontSize should round-trip camera-data expressions.");
@@ -1230,7 +1240,7 @@
@"textIgnoresPlacement should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"true"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textIgnoresPlacement = functionExpression;
mbgl::style::IntervalStops<bool> intervalStops = {{
@@ -1254,8 +1264,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.textIgnoresPlacement = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.textIgnoresPlacement = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -1274,7 +1284,7 @@
@"textJustification should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'right'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textJustification = functionExpression;
mbgl::style::IntervalStops<mbgl::style::TextJustifyType> intervalStops = {{
@@ -1312,7 +1322,7 @@
@"textLetterSpacing should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textLetterSpacing = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -1326,7 +1336,7 @@
XCTAssertEqualObjects(layer.textLetterSpacing, functionExpression,
@"textLetterSpacing should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.textLetterSpacing = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -1334,10 +1344,11 @@
XCTAssertEqual(rawLayer->getTextLetterSpacing(), propertyValue,
@"Setting textLetterSpacing to a data expression should update text-letter-spacing.");
- XCTAssertEqualObjects(layer.textLetterSpacing, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textLetterSpacing, pedanticFunctionExpression,
@"textLetterSpacing should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.textLetterSpacing = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -1347,7 +1358,8 @@
XCTAssertEqual(rawLayer->getTextLetterSpacing(), propertyValue,
@"Setting textLetterSpacing to a camera-data expression should update text-letter-spacing.");
- XCTAssertEqualObjects(layer.textLetterSpacing, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textLetterSpacing, pedanticFunctionExpression,
@"textLetterSpacing should round-trip camera-data expressions.");
@@ -1373,7 +1385,7 @@
@"textLineHeight should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textLineHeight = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -1397,8 +1409,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.textLineHeight = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.textLineHeight = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -1423,7 +1435,7 @@
@"textOffset should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textOffset = functionExpression;
mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
@@ -1437,7 +1449,7 @@
XCTAssertEqualObjects(layer.textOffset, functionExpression,
@"textOffset should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.textOffset = functionExpression;
mbgl::style::ExponentialStops<std::array<float, 2>> exponentialStops = { {{18, { 1, 1 }}}, 1.0 };
@@ -1445,10 +1457,11 @@
XCTAssertEqual(rawLayer->getTextOffset(), propertyValue,
@"Setting textOffset to a data expression should update text-offset.");
- XCTAssertEqualObjects(layer.textOffset, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textOffset, pedanticFunctionExpression,
@"textOffset should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.textOffset = functionExpression;
std::map<float, std::array<float, 2>> innerStops { {18, { 1, 1 }} };
@@ -1458,7 +1471,8 @@
XCTAssertEqual(rawLayer->getTextOffset(), propertyValue,
@"Setting textOffset to a camera-data expression should update text-offset.");
- XCTAssertEqualObjects(layer.textOffset, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textOffset, pedanticFunctionExpression,
@"textOffset should round-trip camera-data expressions.");
@@ -1484,7 +1498,7 @@
@"textOptional should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"true"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textOptional = functionExpression;
mbgl::style::IntervalStops<bool> intervalStops = {{
@@ -1508,8 +1522,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.textOptional = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.textOptional = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -1528,7 +1542,7 @@
@"textPadding should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textPadding = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -1552,8 +1566,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.textPadding = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.textPadding = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -1572,7 +1586,7 @@
@"textPitchAlignment should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'auto'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textPitchAlignment = functionExpression;
mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = {{
@@ -1596,8 +1610,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.textPitchAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.textPitchAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -1616,7 +1630,7 @@
@"textRotation should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textRotation = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -1630,7 +1644,7 @@
XCTAssertEqualObjects(layer.textRotation, functionExpression,
@"textRotation should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.textRotation = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -1638,10 +1652,11 @@
XCTAssertEqual(rawLayer->getTextRotate(), propertyValue,
@"Setting textRotation to a data expression should update text-rotate.");
- XCTAssertEqualObjects(layer.textRotation, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textRotation, pedanticFunctionExpression,
@"textRotation should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.textRotation = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -1651,7 +1666,8 @@
XCTAssertEqual(rawLayer->getTextRotate(), propertyValue,
@"Setting textRotation to a camera-data expression should update text-rotate.");
- XCTAssertEqualObjects(layer.textRotation, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textRotation, pedanticFunctionExpression,
@"textRotation should round-trip camera-data expressions.");
@@ -1677,7 +1693,7 @@
@"textRotationAlignment should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'auto'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textRotationAlignment = functionExpression;
mbgl::style::IntervalStops<mbgl::style::AlignmentType> intervalStops = {{
@@ -1701,8 +1717,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.textRotationAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.textRotationAlignment = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -1721,7 +1737,7 @@
@"textTransform should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'lowercase'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textTransform = functionExpression;
mbgl::style::IntervalStops<mbgl::style::TextTransformType> intervalStops = {{
@@ -1759,7 +1775,7 @@
@"iconColor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconColor = functionExpression;
mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
@@ -1773,7 +1789,7 @@
XCTAssertEqualObjects(layer.iconColor, functionExpression,
@"iconColor should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.iconColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
@@ -1781,10 +1797,11 @@
XCTAssertEqual(rawLayer->getIconColor(), propertyValue,
@"Setting iconColor to a data expression should update icon-color.");
- XCTAssertEqualObjects(layer.iconColor, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconColor, pedanticFunctionExpression,
@"iconColor should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.iconColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
@@ -1794,7 +1811,8 @@
XCTAssertEqual(rawLayer->getIconColor(), propertyValue,
@"Setting iconColor to a camera-data expression should update icon-color.");
- XCTAssertEqualObjects(layer.iconColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconColor, pedanticFunctionExpression,
@"iconColor should round-trip camera-data expressions.");
@@ -1829,7 +1847,7 @@
@"iconHaloBlur should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconHaloBlur = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -1843,7 +1861,7 @@
XCTAssertEqualObjects(layer.iconHaloBlur, functionExpression,
@"iconHaloBlur should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.iconHaloBlur = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -1851,10 +1869,11 @@
XCTAssertEqual(rawLayer->getIconHaloBlur(), propertyValue,
@"Setting iconHaloBlur to a data expression should update icon-halo-blur.");
- XCTAssertEqualObjects(layer.iconHaloBlur, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconHaloBlur, pedanticFunctionExpression,
@"iconHaloBlur should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.iconHaloBlur = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -1864,7 +1883,8 @@
XCTAssertEqual(rawLayer->getIconHaloBlur(), propertyValue,
@"Setting iconHaloBlur to a camera-data expression should update icon-halo-blur.");
- XCTAssertEqualObjects(layer.iconHaloBlur, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconHaloBlur, pedanticFunctionExpression,
@"iconHaloBlur should round-trip camera-data expressions.");
@@ -1899,7 +1919,7 @@
@"iconHaloColor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconHaloColor = functionExpression;
mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
@@ -1913,7 +1933,7 @@
XCTAssertEqualObjects(layer.iconHaloColor, functionExpression,
@"iconHaloColor should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.iconHaloColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
@@ -1921,10 +1941,11 @@
XCTAssertEqual(rawLayer->getIconHaloColor(), propertyValue,
@"Setting iconHaloColor to a data expression should update icon-halo-color.");
- XCTAssertEqualObjects(layer.iconHaloColor, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconHaloColor, pedanticFunctionExpression,
@"iconHaloColor should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.iconHaloColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
@@ -1934,7 +1955,8 @@
XCTAssertEqual(rawLayer->getIconHaloColor(), propertyValue,
@"Setting iconHaloColor to a camera-data expression should update icon-halo-color.");
- XCTAssertEqualObjects(layer.iconHaloColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconHaloColor, pedanticFunctionExpression,
@"iconHaloColor should round-trip camera-data expressions.");
@@ -1969,7 +1991,7 @@
@"iconHaloWidth should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconHaloWidth = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -1983,7 +2005,7 @@
XCTAssertEqualObjects(layer.iconHaloWidth, functionExpression,
@"iconHaloWidth should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.iconHaloWidth = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -1991,10 +2013,11 @@
XCTAssertEqual(rawLayer->getIconHaloWidth(), propertyValue,
@"Setting iconHaloWidth to a data expression should update icon-halo-width.");
- XCTAssertEqualObjects(layer.iconHaloWidth, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconHaloWidth, pedanticFunctionExpression,
@"iconHaloWidth should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.iconHaloWidth = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -2004,7 +2027,8 @@
XCTAssertEqual(rawLayer->getIconHaloWidth(), propertyValue,
@"Setting iconHaloWidth to a camera-data expression should update icon-halo-width.");
- XCTAssertEqualObjects(layer.iconHaloWidth, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconHaloWidth, pedanticFunctionExpression,
@"iconHaloWidth should round-trip camera-data expressions.");
@@ -2039,7 +2063,7 @@
@"iconOpacity should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconOpacity = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -2053,7 +2077,7 @@
XCTAssertEqualObjects(layer.iconOpacity, functionExpression,
@"iconOpacity should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.iconOpacity = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -2061,10 +2085,11 @@
XCTAssertEqual(rawLayer->getIconOpacity(), propertyValue,
@"Setting iconOpacity to a data expression should update icon-opacity.");
- XCTAssertEqualObjects(layer.iconOpacity, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.iconOpacity, pedanticFunctionExpression,
@"iconOpacity should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.iconOpacity = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -2074,7 +2099,8 @@
XCTAssertEqual(rawLayer->getIconOpacity(), propertyValue,
@"Setting iconOpacity to a camera-data expression should update icon-opacity.");
- XCTAssertEqualObjects(layer.iconOpacity, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.iconOpacity, pedanticFunctionExpression,
@"iconOpacity should round-trip camera-data expressions.");
@@ -2115,7 +2141,7 @@
@"iconTranslation should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconTranslation = functionExpression;
mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
@@ -2139,8 +2165,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.iconTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.iconTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -2159,7 +2185,7 @@
@"iconTranslationAnchor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.iconTranslationAnchor = functionExpression;
mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = {{
@@ -2183,8 +2209,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.iconTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.iconTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -2203,7 +2229,7 @@
@"textColor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textColor = functionExpression;
mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
@@ -2217,7 +2243,7 @@
XCTAssertEqualObjects(layer.textColor, functionExpression,
@"textColor should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.textColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
@@ -2225,10 +2251,11 @@
XCTAssertEqual(rawLayer->getTextColor(), propertyValue,
@"Setting textColor to a data expression should update text-color.");
- XCTAssertEqualObjects(layer.textColor, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textColor, pedanticFunctionExpression,
@"textColor should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.textColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
@@ -2238,7 +2265,8 @@
XCTAssertEqual(rawLayer->getTextColor(), propertyValue,
@"Setting textColor to a camera-data expression should update text-color.");
- XCTAssertEqualObjects(layer.textColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textColor, pedanticFunctionExpression,
@"textColor should round-trip camera-data expressions.");
@@ -2273,7 +2301,7 @@
@"textHaloBlur should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textHaloBlur = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -2287,7 +2315,7 @@
XCTAssertEqualObjects(layer.textHaloBlur, functionExpression,
@"textHaloBlur should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.textHaloBlur = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -2295,10 +2323,11 @@
XCTAssertEqual(rawLayer->getTextHaloBlur(), propertyValue,
@"Setting textHaloBlur to a data expression should update text-halo-blur.");
- XCTAssertEqualObjects(layer.textHaloBlur, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textHaloBlur, pedanticFunctionExpression,
@"textHaloBlur should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.textHaloBlur = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -2308,7 +2337,8 @@
XCTAssertEqual(rawLayer->getTextHaloBlur(), propertyValue,
@"Setting textHaloBlur to a camera-data expression should update text-halo-blur.");
- XCTAssertEqualObjects(layer.textHaloBlur, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textHaloBlur, pedanticFunctionExpression,
@"textHaloBlur should round-trip camera-data expressions.");
@@ -2343,7 +2373,7 @@
@"textHaloColor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"%@", [MGLColor redColor]];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textHaloColor = functionExpression;
mbgl::style::IntervalStops<mbgl::Color> intervalStops = {{
@@ -2357,7 +2387,7 @@
XCTAssertEqualObjects(layer.textHaloColor, functionExpression,
@"textHaloColor should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.textHaloColor = functionExpression;
mbgl::style::ExponentialStops<mbgl::Color> exponentialStops = { {{18, { 1, 0, 0, 1 }}}, 1.0 };
@@ -2365,10 +2395,11 @@
XCTAssertEqual(rawLayer->getTextHaloColor(), propertyValue,
@"Setting textHaloColor to a data expression should update text-halo-color.");
- XCTAssertEqualObjects(layer.textHaloColor, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textHaloColor, pedanticFunctionExpression,
@"textHaloColor should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.textHaloColor = functionExpression;
std::map<float, mbgl::Color> innerStops { {18, { 1, 0, 0, 1 }} };
@@ -2378,7 +2409,8 @@
XCTAssertEqual(rawLayer->getTextHaloColor(), propertyValue,
@"Setting textHaloColor to a camera-data expression should update text-halo-color.");
- XCTAssertEqualObjects(layer.textHaloColor, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textHaloColor, pedanticFunctionExpression,
@"textHaloColor should round-trip camera-data expressions.");
@@ -2413,7 +2445,7 @@
@"textHaloWidth should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textHaloWidth = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -2427,7 +2459,7 @@
XCTAssertEqualObjects(layer.textHaloWidth, functionExpression,
@"textHaloWidth should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.textHaloWidth = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -2435,10 +2467,11 @@
XCTAssertEqual(rawLayer->getTextHaloWidth(), propertyValue,
@"Setting textHaloWidth to a data expression should update text-halo-width.");
- XCTAssertEqualObjects(layer.textHaloWidth, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textHaloWidth, pedanticFunctionExpression,
@"textHaloWidth should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.textHaloWidth = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -2448,7 +2481,8 @@
XCTAssertEqual(rawLayer->getTextHaloWidth(), propertyValue,
@"Setting textHaloWidth to a camera-data expression should update text-halo-width.");
- XCTAssertEqualObjects(layer.textHaloWidth, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textHaloWidth, pedanticFunctionExpression,
@"textHaloWidth should round-trip camera-data expressions.");
@@ -2483,7 +2517,7 @@
@"textOpacity should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"0xff"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textOpacity = functionExpression;
mbgl::style::IntervalStops<float> intervalStops = {{
@@ -2497,7 +2531,7 @@
XCTAssertEqualObjects(layer.textOpacity, functionExpression,
@"textOpacity should round-trip camera expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(keyName, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(keyName, 'linear', nil, %@)", @{@18: constantExpression}];
layer.textOpacity = functionExpression;
mbgl::style::ExponentialStops<float> exponentialStops = { {{18, 0xff}}, 1.0 };
@@ -2505,10 +2539,11 @@
XCTAssertEqual(rawLayer->getTextOpacity(), propertyValue,
@"Setting textOpacity to a data expression should update text-opacity.");
- XCTAssertEqualObjects(layer.textOpacity, functionExpression,
+ NSExpression *pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:(CAST(keyName, 'NSNumber'), 'linear', nil, %@)", @{@18: constantExpression}];
+ XCTAssertEqualObjects(layer.textOpacity, pedanticFunctionExpression,
@"textOpacity should round-trip data expressions.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
layer.textOpacity = functionExpression;
std::map<float, float> innerStops { {18, 0xff} };
@@ -2518,7 +2553,8 @@
XCTAssertEqual(rawLayer->getTextOpacity(), propertyValue,
@"Setting textOpacity to a camera-data expression should update text-opacity.");
- XCTAssertEqualObjects(layer.textOpacity, functionExpression,
+ pedanticFunctionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: pedanticFunctionExpression}];
+ XCTAssertEqualObjects(layer.textOpacity, pedanticFunctionExpression,
@"textOpacity should round-trip camera-data expressions.");
@@ -2559,7 +2595,7 @@
@"textTranslation should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"{1, 1}"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textTranslation = functionExpression;
mbgl::style::IntervalStops<std::array<float, 2>> intervalStops = {{
@@ -2583,8 +2619,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.textTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.textTranslation = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
@@ -2603,7 +2639,7 @@
@"textTranslationAnchor should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'viewport'"];
- NSExpression *functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
+ NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.textTranslationAnchor = functionExpression;
mbgl::style::IntervalStops<mbgl::style::TranslateAnchorType> intervalStops = {{
@@ -2627,8 +2663,8 @@
functionExpression = [NSExpression expressionForKeyPath:@"bogus"];
XCTAssertThrowsSpecificNamed(layer.textTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION(bogus, 'mgl_stepWithMinimum:stops:', %@, %@)", constantExpression, @{@18: constantExpression}];
- functionExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{@10: functionExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:(bogus, %@, %@)", constantExpression, @{@18: constantExpression}];
+ functionExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{@10: functionExpression}];
XCTAssertThrowsSpecificNamed(layer.textTranslationAnchor = functionExpression, NSException, NSInvalidArgumentException, @"MGLSymbolLayer should raise an exception if a camera-data expression is applied to a property that does not support key paths to feature attributes.");
}
}
diff --git a/platform/darwin/test/MGLTileSetTests.mm b/platform/darwin/test/MGLTileSetTests.mm
index 74c84184e1..2319f66447 100644
--- a/platform/darwin/test/MGLTileSetTests.mm
+++ b/platform/darwin/test/MGLTileSetTests.mm
@@ -66,8 +66,16 @@
// when the tile set has attribution infos
MGLAttributionInfo *mapboxInfo = [[MGLAttributionInfo alloc] initWithTitle:[[NSAttributedString alloc] initWithString:@"Mapbox"]
URL:[NSURL URLWithString:@"https://www.mapbox.com/"]];
+#if TARGET_OS_IPHONE
+ UIColor *redColor = [UIColor redColor];
+#else
+ // CSS uses the sRGB color space. In macOS 10.12 Sierra and below,
+ // -[NSColor redColor] is in the calibrated RGB space and has a slightly
+ // different sRGB value than on iOS and macOS 10.13 High Sierra.
+ NSColor *redColor = [NSColor colorWithSRGBRed:1 green:0 blue:0 alpha:1];
+#endif
NSAttributedString *gl = [[NSAttributedString alloc] initWithString:@"GL" attributes:@{
- NSBackgroundColorAttributeName: [MGLColor redColor],
+ NSBackgroundColorAttributeName: redColor,
}];
MGLAttributionInfo *glInfo = [[MGLAttributionInfo alloc] initWithTitle:gl URL:nil];
tileSet = MGLTileSetFromTileURLTemplates(tileURLTemplates, @{
@@ -82,7 +90,7 @@
#else
NSString *html = (@"<font face=\"Helvetica\" size=\"3\" style=\"font: 12.0px Helvetica\">"
@"<a href=\"https://www.mapbox.com/\">Mapbox</a> </font>"
- @"<font face=\"Helvetica\" size=\"3\" style=\"font: 12.0px Helvetica; background-color: #ff2600\">GL</font>\n");
+ @"<font face=\"Helvetica\" size=\"3\" style=\"font: 12.0px Helvetica; background-color: #ff0000\">GL</font>\n");
#endif
XCTAssertEqualObjects(@(tileSet.attribution.c_str()), html);
diff --git a/platform/default/mbgl/util/default_styles.hpp b/platform/default/mbgl/util/default_styles.hpp
index 43dafb8083..13f08252a7 100644
--- a/platform/default/mbgl/util/default_styles.hpp
+++ b/platform/default/mbgl/util/default_styles.hpp
@@ -19,12 +19,9 @@ constexpr const DefaultStyle light = { "mapbox://styles/mapbox/light-
constexpr const DefaultStyle dark = { "mapbox://styles/mapbox/dark-v9", "Dark", 9 };
constexpr const DefaultStyle satellite = { "mapbox://styles/mapbox/satellite-v9", "Satellite", 9 };
constexpr const DefaultStyle satelliteStreets = { "mapbox://styles/mapbox/satellite-streets-v10", "Satellite Streets", 10 };
-constexpr const DefaultStyle trafficDay = { "mapbox://styles/mapbox/traffic-day-v2", "Traffic Day", 2 };
-constexpr const DefaultStyle trafficNight = { "mapbox://styles/mapbox/traffic-night-v2", "Traffic Night", 2 };
const DefaultStyle orderedStyles[] = {
streets, outdoors, light, dark, satellite, satelliteStreets,
- trafficDay, trafficNight,
};
const size_t numOrderedStyles = sizeof(orderedStyles) / sizeof(DefaultStyle);
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index 7c2fa639c1..9d8390803b 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -2,36 +2,91 @@
Mapbox welcomes participation and contributions from everyone. Please read [CONTRIBUTING.md](../../CONTRIBUTING.md) to get started.
-## master
+## 4.0.1
+
+### Style layers
+
+* Deprecated `+[NSExpression featurePropertiesVariableExpression]` use `+[NSExpression featureAttributesVariableExpression]` instead. ([#11748](https://github.com/mapbox/mapbox-gl-native/pull/11748))
+
+## 4.0.0 - April 19, 2018
+
+The 4.0._x_ series of releases will be the last to support iOS 8. The minimum iOS deployment version will increase to iOS 9.0 in a future release.
### Packaging
* Removed support for 32-bit simulators. ([#10962](https://github.com/mapbox/mapbox-gl-native/pull/10962))
+* Added Danish, Hebrew, and European Portuguese localizations. ([#10967](https://github.com/mapbox/mapbox-gl-native/pull/10967), [#11136](https://github.com/mapbox/mapbox-gl-native/pull/11134), [#11695](https://github.com/mapbox/mapbox-gl-native/pull/11695))
+* Removed methods, properties, and constants that had been deprecated as of v3.7.6. ([#11205](https://github.com/mapbox/mapbox-gl-native/pull/11205), [#11681](https://github.com/mapbox/mapbox-gl-native/pull/11681))
+* Refined certain Swift interfaces by converting them from class methods to class properties. ([#11674](https://github.com/mapbox/mapbox-gl-native/pull/11674))
+* Revamped the “Adding Points to a Map” guide. ([#11496](https://github.com/mapbox/mapbox-gl-native/pull/11496))
-### Styles and rendering
+### Style layers
-* Added support for a new layer type: `MGLHeatmapStyleLayer`, a powerful way to visualize point data distributions using heatmaps, fully customizable through runtime styling. [#11046](https://github.com/mapbox/mapbox-gl-native/pull/11046)
-* The layout and paint properties on subclasses of `MGLStyleLayer` are now of type `NSExpression` instead of `MGLStyleValue`. A new “Predicates and Expressions” guide provides an overview of the supported operators. ([#10726](https://github.com/mapbox/mapbox-gl-native/pull/10726))
+* The layout and paint properties on subclasses of `MGLStyleLayer` are now of type `NSExpression` instead of `MGLStyleValue`. A new “Predicates and Expressions” guide provides an overview of the supported operators, which include arithmetic and conditional operators. ([#10726](https://github.com/mapbox/mapbox-gl-native/pull/10726))
+* A style can now display a heatmap layer that visualizes a point data distribution. You can customize the appearance at runtime using the `MGLHeatmapStyleLayer` class. ([#11046](https://github.com/mapbox/mapbox-gl-native/pull/11046))
+* A style can now display a smooth hillshading layer and customize its appearance at runtime using the `MGLHillshadeStyleLayer` class. Hillshading is based on a rasterized digital elevation model supplied by the `MGLRasterDEMSource` class. ([#10642](https://github.com/mapbox/mapbox-gl-native/pull/10642))
+* You can now set the `MGLVectorStyleLayer.predicate` property to a predicate that contains arithmetic and calls to built-in `NSExpression` functions. You may need to cast a feature attribute key to `NSString` or `NSNumber` before comparing it to a string or number. ([#11587](https://github.com/mapbox/mapbox-gl-native/pull/11587))
+* Replaced the `MGLStyle.localizesLabels` property with an `-[MGLStyle localizeLabelsIntoLocale:]` method that allows you to specify the language to localize into. Also added an `-[NSExpression(MGLAdditions) mgl_expressionLocalizedIntoLocale:]` method for localizing an individual value used with `MGLSymbolStyleLayer.text`. ([#11651](https://github.com/mapbox/mapbox-gl-native/pull/11651))
+* The `MGLSymbolStyleLayer.textFontNames` property can now depend on a feature’s attributes. ([#10850](https://github.com/mapbox/mapbox-gl-native/pull/10850))
+* Changes to the `MGLStyleLayer.minimumZoomLevel` and `MGLStyleLayer.maximumZoomLevel` properties take effect immediately. ([#11399](https://github.com/mapbox/mapbox-gl-native/pull/11399))
+
+### Content sources
+
+* Renamed `MGLRasterSource` to `MGLRasterTileSource` and `MGLVectorSource` to `MGLVectorTileSource`. ([#11568](https://github.com/mapbox/mapbox-gl-native/pull/11568))
* Added an `MGLComputedShapeSource` class that allows applications to supply vector data to a style layer on a per-tile basis. ([#9983](https://github.com/mapbox/mapbox-gl-native/pull/9983))
-* A style can now display smooth hillshading and customize its appearance at runtime using the `MGLHillshadeStyleLayer` class. Hillshading is based on a rasterized digital elevation model supplied by the `MGLRasterDEMSource` class. ([#10642](https://github.com/mapbox/mapbox-gl-native/pull/10642))
* Properties such as `MGLSymbolStyleLayer.iconAllowsOverlap` and `MGLSymbolStyleLayer.iconIgnoresPlacement` now account for symbols in other sources. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))
+
+### Map rendering
+
* Improved the reliability of collision detection between symbols near the edges of tiles, as well as between symbols when the map is tilted. It is no longer necessary to enable `MGLSymbolStyleLayer.symbolAvoidsEdges` to prevent symbols in adjacent tiles from overlapping with each other. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))
* Symbols can fade in and out as the map pans, rotates, or tilts. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))
* Fixed an issue preventing a dynamically-added `MGLRasterStyleLayer` from drawing until the map pans. ([#10270](https://github.com/mapbox/mapbox-gl-native/pull/10270))
* Fixed an issue preventing `MGLImageSource`s from drawing on the map when the map is zoomed in and tilted. ([#10677](https://github.com/mapbox/mapbox-gl-native/pull/10677))
-
-### Snapshots
-
-* Fixed a memory leak that occurred when creating a map snapshot. ([#10585](https://github.com/mapbox/mapbox-gl-native/pull/10585))
+* Improved the sharpness of raster tiles on Retina displays. ([#10984](https://github.com/mapbox/mapbox-gl-native/pull/10984))
+* Fixed a crash parsing a malformed style. ([#11001](https://github.com/mapbox/mapbox-gl-native/pull/11001))
+* Reduced memory usage by clearing in-memory tile cache before entering background. ([#11197](https://github.com/mapbox/mapbox-gl-native/pull/11197))
+* Fixed an issue where symbols with empty labels would always be hidden. ([#11206](https://github.com/mapbox/mapbox-gl-native/pull/11206))
+* Fixed an issue where a tilted map could flicker while displaying rotating symbols. ([#11488](https://github.com/mapbox/mapbox-gl-native/pull/11488))
+* Increased the maximum width of labels by a factor of two. ([#11508](https://github.com/mapbox/mapbox-gl-native/pull/11508))
### Annotations
+* Changed the default value of `MGLAnnotationView.scalesWithViewingDistance` to `NO`, to improve performance. If your use case involves many annotation views, consider keeping this property disabled. ([#11636](https://github.com/mapbox/mapbox-gl-native/pull/11636))
+* Fixed an issue preventing `MGLAnnotationImage.image` from being updated. ([#10372](https://github.com/mapbox/mapbox-gl-native/pull/10372))
* Improved performance of `MGLAnnotationView`-backed annotations that have `scalesWithViewingDistance` enabled. ([#10951](https://github.com/mapbox/mapbox-gl-native/pull/10951))
+* Fixed an issue where tapping a group of annotations may not have selected the nearest annotation. ([#11438](https://github.com/mapbox/mapbox-gl-native/pull/11438))
+* The `MGLMapView.selectedAnnotations` property (backed by `-[MGLMapView setSelectedAnnotations:]`) now selects annotations that are off-screen. ([#9790](https://github.com/mapbox/mapbox-gl-native/issues/9790))
+* The `animated` parameter to `-[MGLMapView selectAnnotation:animated:]` now controls whether the annotation and its callout are brought on-screen. If `animated` is `NO` then the annotation is selected if offscreen, but the map is not panned. Currently only point annotations are supported. Setting the `MGLMapView.selectedAnnotations` property now animates. ([#3249](https://github.com/mapbox/mapbox-gl-native/issues/3249))
+* Fixed a crash when rapidly adding and removing annotations. ([#11551](https://github.com/mapbox/mapbox-gl-native/issues/11551), [#11575](https://github.com/mapbox/mapbox-gl-native/issues/11575))
+* Marked protocol method `-[MGLCalloutView presentCalloutFromRect:inView:constrainedToView:animated:]` as unavailable. Use `-[MGLCalloutView presentCalloutFromRect:inView:constrainedToRect:animated:]` instead. ([#11738](https://github.com/mapbox/mapbox-gl-native/pull/11738))
+
+### Map snapshots
+
+* Fixed a memory leak that occurred when creating a map snapshot. ([#10585](https://github.com/mapbox/mapbox-gl-native/pull/10585))
### Other changes
-* Added a Hebrew localization. ([#10967](https://github.com/mapbox/mapbox-gl-native/pull/10967))
+* The `-[MGLMapView convertRect:toCoordinateBoundsFromView:]` method and the `MGLMapView.visibleCoordinateBounds` property’s getter now indicate that the coordinate bounds straddles the antimeridian by extending one side beyond ±180 degrees longitude. ([#11265](https://github.com/mapbox/mapbox-gl-native/pull/11265))
+* Feature querying results now account for the `MGLSymbolStyleLayer.circleStrokeWidth` property. ([#10897](https://github.com/mapbox/mapbox-gl-native/pull/10897))
+* Fixed an issue preventing labels from being transliterated when VoiceOver was enabled on iOS 10._x_ and below. ([#10881](https://github.com/mapbox/mapbox-gl-native/pull/10881))
+* Labels are now transliterated from more languages when VoiceOver is enabled. ([#10881](https://github.com/mapbox/mapbox-gl-native/pull/10881))
* Long-pressing the attribution button causes the SDK’s version number to be displayed in the action sheet that appears. ([#10650](https://github.com/mapbox/mapbox-gl-native/pull/10650))
+* Reduced offline download sizes for styles with symbol layers that render only icons, and no text. ([#11055](https://github.com/mapbox/mapbox-gl-native/pull/11055))
+* Added haptic feedback that occurs when the user rotates the map to due north, configurable via `MGLMapView.hapticFeedbackEnabled`. ([#10847](https://github.com/mapbox/mapbox-gl-native/pull/10847))
+* Added `MGLMapView.showsScale` as the recommended way to show the scale bar. This property can be set directly in Interface Builder. ([#11335](https://github.com/mapbox/mapbox-gl-native/pull/11335))
+* Fixed an issue where the scale bar would not appear until the map had moved. ([#11335](https://github.com/mapbox/mapbox-gl-native/pull/11335))
+
+## 3.7.6 - March 12, 2018
+
+* Fixed an issue where full-resolution tiles could fail to replace lower-resolution placeholders. ([#11227](https://github.com/mapbox/mapbox-gl-native/pull/11227))
+* Fixed an issue where tilesets with bounds that cover the entire world would fail to render. ([#11425](https://github.com/mapbox/mapbox-gl-native/pull/11425))
+* Fixed a memory leak in `MGLMapSnapshotter`. ([#11193](https://github.com/mapbox/mapbox-gl-native/pull/11193))
+* Fixed an issue where the pinch gesture could drift beyond bounds imposed by `-[MGLMapViewDelegate mapView:shouldChangeFromCamera:toCamera:]`. ([#11423](https://github.com/mapbox/mapbox-gl-native/pull/11423))
+* Improved the visibility of the heading indicator arrow. ([#11337](https://github.com/mapbox/mapbox-gl-native/pull/11337))
+
+## 3.7.5 - February 16, 2018
+
+* Fixed an issue where requesting location services permission would trigger an unrecoverable loop. ([#11229](https://github.com/mapbox/mapbox-gl-native/pull/11229))
## 3.7.6 - March 12, 2018
diff --git a/platform/ios/DEVELOPING.md b/platform/ios/DEVELOPING.md
index 10a94c73f3..7a97074d38 100644
--- a/platform/ios/DEVELOPING.md
+++ b/platform/ios/DEVELOPING.md
@@ -4,7 +4,7 @@ This document explains how to build the Mapbox Maps SDK for iOS from source. It
## Requirements
-The Mapbox Maps SDK for iOS and iosapp demo application require iOS 8.0 or above.
+The Mapbox Maps SDK for iOS and iosapp demo application require iOS 8.0 or above. _Note: Support for iOS 8 will be removed in a future release and the minimum iOS deployment version will increase to iOS 9.0._
The Mapbox Maps SDK for iOS requires Xcode 9.1 or above to compile from source.
@@ -139,6 +139,8 @@ To add an example code listing to the documentation for a class or class member:
to [MGLDocumentationExampleTests](test/MGLDocumentationExampleTests.swift).
Wrap the code you’d like to appear in the documentation within
`//#-example-code` and `//#-end-example-code` comments.
+1. If the header doesn’t already have an example code listing, add the path to
+ the header to platform/darwin/scripts/update-examples.list.
1. Insert the code listings into the headers:
```bash
diff --git a/platform/ios/INSTALL.md b/platform/ios/INSTALL.md
index 3aef7db6f4..01f4621b1e 100644
--- a/platform/ios/INSTALL.md
+++ b/platform/ios/INSTALL.md
@@ -10,6 +10,8 @@ The Mapbox Maps SDK for iOS is intended to run on iOS 8.0 and above on the follo
* iPad 2 and above (3, 4, Mini, Air, Mini 2, Air 2, Pro)
* iPod touch 5th generation and above
+_Note: Support for iOS 8 will be removed in a future release and the minimum iOS deployment version will increase to iOS 9.0._
+
Note that 32-bit simulators (such as the iPhone 5 or iPad 2) are not supported.
The Mapbox Maps SDK for iOS requires:
diff --git a/platform/ios/Integration Tests/MBGLIntegrationTests.m b/platform/ios/Integration Tests/MBGLIntegrationTests.m
index db6cc13930..4f42c5a13f 100644
--- a/platform/ios/Integration Tests/MBGLIntegrationTests.m
+++ b/platform/ios/Integration Tests/MBGLIntegrationTests.m
@@ -1,68 +1,103 @@
-#import <XCTest/XCTest.h>
+#import "MGLMapViewIntegrationTest.h"
-@import Mapbox;
+@interface MBGLIntegrationTests : MGLMapViewIntegrationTest
+@end
-@interface MBGLIntegrationTests : XCTestCase <MGLMapViewDelegate>
+@implementation MBGLIntegrationTests
-@property (nonatomic) MGLMapView *mapView;
-@property (nonatomic) MGLStyle *style;
+#pragma mark - Tests
-@end
+- (void)waitForMapViewToBeRendered {
+ [self waitForMapViewToBeRenderedWithTimeout:1];
+}
+
+// This test does not strictly need to be in this test file/target. Including here for convenience.
+- (void)testOpenGLLayerDoesNotLeakWhenCreatedAndDestroyedWithoutAddingToStyle {
+ MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ __weak id weakLayer = layer;
+ layer = nil;
-@implementation MBGLIntegrationTests {
- XCTestExpectation *_styleLoadingExpectation;
+ XCTAssertNil(weakLayer);
}
-- (void)setUp {
- [super setUp];
+- (void)testAddingRemovingOpenGLLayerWithoutRendering {
+ XCTAssertNotNil(self.style);
- [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"];
- NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
- self.mapView = [[MGLMapView alloc] initWithFrame:UIScreen.mainScreen.bounds styleURL:styleURL];
- self.mapView.delegate = self;
- if (!self.mapView.style) {
- _styleLoadingExpectation = [self expectationWithDescription:@"Map view should finish loading style."];
- [self waitForExpectationsWithTimeout:1 handler:nil];
- }
+ void(^addRemoveGLLayer)(void) = ^{
+ __weak id weakLayer = nil;
- UIView *superView = [[UIView alloc] initWithFrame:UIScreen.mainScreen.bounds];
- [superView addSubview:self.mapView];
- UIWindow *window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
- [window addSubview:superView];
- [window makeKeyAndVisible];
-}
+ @autoreleasepool {
+ MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ [self.style insertLayer:layer atIndex:0];
+ weakLayer = layer;
-- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
- XCTAssertNotNil(mapView.style);
- XCTAssertEqual(mapView.style, style);
+ // Nil the layer prior to remove to ensure it's being retained
+ layer = nil;
+ [self.style removeLayer:weakLayer];
+ }
+
+ XCTAssertNil(weakLayer);
+ };
- [_styleLoadingExpectation fulfill];
+ addRemoveGLLayer();
+ addRemoveGLLayer();
+ addRemoveGLLayer();
}
-- (void)tearDown {
- _styleLoadingExpectation = nil;
- self.mapView = nil;
+- (void)testReusingOpenGLLayerIdentifier {
+ __weak MGLOpenGLStyleLayer *weakLayer2;
- [super tearDown];
-}
+ @autoreleasepool {
+ MGLOpenGLStyleLayer *layer1 = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ [self.style insertLayer:layer1 atIndex:0];
+ [self waitForMapViewToBeRendered];
+ [self.style removeLayer:layer1];
-- (MGLStyle *)style {
- return self.mapView.style;
+ MGLOpenGLStyleLayer *layer2 = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ weakLayer2 = layer2;
+
+ XCTAssertNotNil(layer2);
+ XCTAssert(layer1 != layer2);
+
+ [self.style insertLayer:layer2 atIndex:0];
+ [self waitForMapViewToBeRendered];
+ [self.style removeLayer:layer2];
+
+ XCTAssertNil([layer1 style]);
+ XCTAssertNil([layer2 style]);
+ }
+
+ // At this point, layer2 (and layer1) should still be around,
+ // since the render process needs to keep a reference to them.
+ XCTAssertNotNil(weakLayer2);
+
+ // Let render loop run enough to release the layers
+ [self waitForMapViewToBeRendered];
+ XCTAssertNil(weakLayer2);
}
- (void)testAddingRemovingOpenGLLayer {
XCTAssertNotNil(self.style);
void(^addRemoveGLLayer)(void) = ^{
- MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
- [self.style insertLayer:layer atIndex:0];
- layer = nil;
- [[NSRunLoop currentRunLoop] runUntilDate:[NSDate date]];
+ __weak id retrievedLayer = nil;
+
+ @autoreleasepool {
+ MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ [self.style insertLayer:layer atIndex:0];
+ layer = nil;
+
+ [self waitForMapViewToBeRendered];
+
+ retrievedLayer = [self.style layerWithIdentifier:@"gl-layer"];
+ XCTAssertNotNil(retrievedLayer);
- id retrievedLayer = [self.style layerWithIdentifier:@"gl-layer"];
- XCTAssertNotNil(retrievedLayer);
- [self.style removeLayer:retrievedLayer];
+ [self.style removeLayer:retrievedLayer];
+ [self waitForMapViewToBeRendered];
+ }
+
+ XCTAssertNil(retrievedLayer);
};
addRemoveGLLayer();
@@ -70,8 +105,98 @@
addRemoveGLLayer();
}
-//- (void)testOpenGLLayerDoesNotLeakWhenCreatedAndDestroyedWithoutAddingToStyle {
-// XCTFail(@"Not yet implemented");
-//}
+- (void)testReusingOpenGLLayer {
+ MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ [self.style insertLayer:layer atIndex:0];
+ [self waitForMapViewToBeRendered];
+
+ [self.style removeLayer:layer];
+ [self waitForMapViewToBeRendered];
+
+ [self.style insertLayer:layer atIndex:0];
+ [self waitForMapViewToBeRendered];
+
+ [self.style removeLayer:layer];
+ [self waitForMapViewToBeRendered];
+}
+
+- (void)testOpenGLLayerDoesNotLeakWhenRemovedFromStyle {
+ __weak id weakLayer;
+ @autoreleasepool {
+ MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ weakLayer = layer;
+ [self.style insertLayer:layer atIndex:0];
+ layer = nil;
+
+ [self waitForMapViewToBeRendered];
+ [self.style removeLayer:[self.style layerWithIdentifier:@"gl-layer"]];
+ }
+
+ MGLStyleLayer *layer2 = weakLayer;
+
+ XCTAssertNotNil(weakLayer);
+ [self waitForMapViewToBeRendered];
+
+ layer2 = nil;
+ XCTAssertNil(weakLayer);
+}
+
+- (void)testOpenGLLayerDoesNotLeakWhenStyleChanged {
+ __weak MGLOpenGLStyleLayer *weakLayer;
+
+ @autoreleasepool {
+ {
+ MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ weakLayer = layer;
+ [self.style insertLayer:layer atIndex:0];
+ layer = nil;
+ }
+ }
+
+ XCTAssertNotNil(weakLayer);
+
+ [self waitForMapViewToBeRendered];
+
+ MGLStyleLayer *layer2 = [self.mapView.style layerWithIdentifier:@"gl-layer"];
+
+ NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
+ self.styleLoadingExpectation = [self expectationWithDescription:@"Map view should finish loading style."];
+ [self.mapView setStyleURL:styleURL];
+ [self waitForExpectations:@[self.styleLoadingExpectation] timeout:10];
+
+ // At this point the C++ CustomLayer will have been destroyed, and the rawLayer pointer has been NULLed
+ XCTAssert(weakLayer == layer2);
+ XCTAssertNotNil(weakLayer);
+
+ // Asking the style for the layer should return nil
+ MGLStyleLayer *layer3 = [self.mapView.style layerWithIdentifier:@"gl-layer"];
+ XCTAssertNil(layer3);
+}
+
+
+- (void)testOpenGLLayerDoesNotLeakWhenMapViewDeallocs {
+ __weak id weakLayer;
+
+ @autoreleasepool {
+
+ NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
+ MGLMapView *mapView2 = [[MGLMapView alloc] initWithFrame:UIScreen.mainScreen.bounds styleURL:styleURL];
+ mapView2.delegate = self;
+
+ XCTAssertNil(mapView2.style);
+
+ self.styleLoadingExpectation = [self expectationWithDescription:@"Map view should finish loading style."];
+ [self waitForExpectationsWithTimeout:1 handler:nil];
+
+ MGLOpenGLStyleLayer *layer = [[MGLOpenGLStyleLayer alloc] initWithIdentifier:@"gl-layer"];
+ weakLayer = layer;
+ [mapView2.style insertLayer:layer atIndex:0];
+ layer = nil;
+
+ [self waitForMapViewToBeRendered];
+ }
+ XCTAssertNil(weakLayer);
+}
@end
+
diff --git a/platform/ios/Integration Tests/MGLMapViewIntegrationTest.h b/platform/ios/Integration Tests/MGLMapViewIntegrationTest.h
new file mode 100644
index 0000000000..ab5d2cc46f
--- /dev/null
+++ b/platform/ios/Integration Tests/MGLMapViewIntegrationTest.h
@@ -0,0 +1,20 @@
+#import <XCTest/XCTest.h>
+#import <Mapbox/Mapbox.h>
+
+#define TestFailWithSelf(myself, ...) \
+ _XCTPrimitiveFail(myself, __VA_ARGS__)
+
+@interface MGLMapViewIntegrationTest : XCTestCase <MGLMapViewDelegate>
+@property (nonatomic) MGLMapView *mapView;
+@property (nonatomic) MGLStyle *style;
+@property (nonatomic) XCTestExpectation *styleLoadingExpectation;
+@property (nonatomic) XCTestExpectation *renderFinishedExpectation;
+@property (nonatomic) void (^regionDidChange)(MGLMapView *mapView, BOOL animated);
+@property (nonatomic) void (^regionIsChanging)(MGLMapView *mapView);
+
+
+
+// Utility methods
+- (void)waitForMapViewToFinishLoadingStyleWithTimeout:(NSTimeInterval)timeout;
+- (void)waitForMapViewToBeRenderedWithTimeout:(NSTimeInterval)timeout;
+@end
diff --git a/platform/ios/Integration Tests/MGLMapViewIntegrationTest.m b/platform/ios/Integration Tests/MGLMapViewIntegrationTest.m
new file mode 100644
index 0000000000..fc3229c83b
--- /dev/null
+++ b/platform/ios/Integration Tests/MGLMapViewIntegrationTest.m
@@ -0,0 +1,79 @@
+#import "MGLMapViewIntegrationTest.h"
+
+@implementation MGLMapViewIntegrationTest
+
+- (void)setUp {
+ [super setUp];
+
+ [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"];
+ NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:UIScreen.mainScreen.bounds styleURL:styleURL];
+ self.mapView.delegate = self;
+
+ UIView *superView = [[UIView alloc] initWithFrame:UIScreen.mainScreen.bounds];
+ [superView addSubview:self.mapView];
+ UIWindow *window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
+ [window addSubview:superView];
+ [window makeKeyAndVisible];
+
+ if (!self.mapView.style) {
+ [self waitForMapViewToFinishLoadingStyleWithTimeout:1];
+ }
+}
+
+- (void)tearDown {
+ self.styleLoadingExpectation = nil;
+ self.renderFinishedExpectation = nil;
+ self.mapView = nil;
+ self.style = nil;
+
+ [super tearDown];
+}
+
+#pragma mark - MGLMapViewDelegate
+
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+ XCTAssertNotNil(mapView.style);
+ XCTAssertEqual(mapView.style, style);
+
+ [self.styleLoadingExpectation fulfill];
+}
+
+- (void)mapViewDidFinishRenderingFrame:(MGLMapView *)mapView fullyRendered:(__unused BOOL)fullyRendered {
+ [self.renderFinishedExpectation fulfill];
+ self.renderFinishedExpectation = nil;
+}
+
+- (void)mapView:(MGLMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
+ if (self.regionDidChange) {
+ self.regionDidChange(mapView, animated);
+ }
+}
+
+- (void)mapViewRegionIsChanging:(MGLMapView *)mapView {
+ if (self.regionIsChanging) {
+ self.regionIsChanging(mapView);
+ }
+}
+
+#pragma mark - Utilities
+
+- (void)waitForMapViewToFinishLoadingStyleWithTimeout:(NSTimeInterval)timeout {
+ XCTAssertNil(self.styleLoadingExpectation);
+ self.styleLoadingExpectation = [self expectationWithDescription:@"Map view should finish loading style."];
+ [self waitForExpectations:@[self.styleLoadingExpectation] timeout:timeout];
+}
+
+- (void)waitForMapViewToBeRenderedWithTimeout:(NSTimeInterval)timeout {
+ XCTAssertNil(self.renderFinishedExpectation);
+ [self.mapView setNeedsDisplay];
+ self.renderFinishedExpectation = [self expectationWithDescription:@"Map view should be rendered"];
+ [self waitForExpectations:@[self.renderFinishedExpectation] timeout:timeout];
+}
+
+- (MGLStyle *)style {
+ return self.mapView.style;
+}
+
+@end
diff --git a/platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec b/platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec
index 268b7b9da6..7ea1b993ef 100644
--- a/platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec
+++ b/platform/ios/Mapbox-iOS-SDK-nightly-dynamic.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |m|
- version = '3.7.6'
+ version = '4.0.0'
m.name = 'Mapbox-iOS-SDK-nightly-dynamic'
m.version = "#{version}-nightly"
diff --git a/platform/ios/Mapbox-iOS-SDK-symbols.podspec b/platform/ios/Mapbox-iOS-SDK-symbols.podspec
index a1b2441d29..47a021598f 100644
--- a/platform/ios/Mapbox-iOS-SDK-symbols.podspec
+++ b/platform/ios/Mapbox-iOS-SDK-symbols.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |m|
- version = '3.7.6'
+ version = '4.0.0'
m.name = 'Mapbox-iOS-SDK-symbols'
m.version = "#{version}-symbols"
diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec
index 7e696a23cf..73412890c8 100644
--- a/platform/ios/Mapbox-iOS-SDK.podspec
+++ b/platform/ios/Mapbox-iOS-SDK.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |m|
- version = '3.7.6'
+ version = '4.0.0'
m.name = 'Mapbox-iOS-SDK'
m.version = version
diff --git a/platform/ios/Mapbox.playground/Contents.swift b/platform/ios/Mapbox.playground/Contents.swift
index 1f368be73b..f31c9b6171 100644
--- a/platform/ios/Mapbox.playground/Contents.swift
+++ b/platform/ios/Mapbox.playground/Contents.swift
@@ -1,9 +1,5 @@
import UIKit
-#if swift(>=3)
- import PlaygroundSupport
-#else
- import XCPlayground
-#endif
+import PlaygroundSupport
import Mapbox
let width: CGFloat = 700
@@ -11,13 +7,9 @@ let height: CGFloat = 800
class Responder: NSObject {
var mapView: MGLMapView?
- func togglePitch(sender: UISwitch) {
+ @objc func togglePitch(sender: UISwitch) {
let camera = mapView!.camera
- #if swift(>=3)
- camera.pitch = sender.isOn ? 60 : 0
- #else
- camera.pitch = sender.on ? 60 : 0
- #endif
+ camera.pitch = sender.isOn ? 60 : 0
mapView!.setCamera(camera, animated: false)
}
}
@@ -26,11 +18,7 @@ class Responder: NSObject {
let panelWidth: CGFloat = 200
let panel = UIView(frame: CGRect(x: width - panelWidth, y: 0, width: 200, height: 100))
panel.alpha = 0.8
-#if swift(>=3)
- panel.backgroundColor = .white
-#else
- panel.backgroundColor = UIColor.whiteColor()
-#endif
+panel.backgroundColor = .white
// Delete markers
let deleteSwitchLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 100, height: 30))
@@ -53,11 +41,7 @@ let pitchLabel = UILabel(frame: CGRect(x: 0, y: 60, width: 100, height: 30))
pitchLabel.text = "Pitch"
let pitchSwitch = UISwitch(frame: CGRect(x: panelWidth-panelWidth / 2.0, y: 60, width: 100, height: 50))
let responder = Responder()
-#if swift(>=3)
- pitchSwitch.addTarget(responder, action: #selector(responder.togglePitch(sender:)), for: .valueChanged)
-#else
- pitchSwitch.addTarget(responder, action: #selector(responder.togglePitch(_:)), forControlEvents: .ValueChanged)
-#endif
+pitchSwitch.addTarget(responder, action: #selector(responder.togglePitch(sender:)), for: .valueChanged)
panel.addSubview(pitchLabel)
panel.addSubview(pitchSwitch)
@@ -67,16 +51,12 @@ panel.addSubview(pitchSwitch)
Put your access token into a plain text file called `token`. Then select the “token” placeholder below, go to Editor ‣ Insert File Literal, and select the `token` file.
*/
var accessToken = try String(contentsOfURL: <#token#>)
-MGLAccountManager.setAccessToken(accessToken)
+MGLAccountManager.accessToken = accessToken
class PlaygroundAnnotationView: MGLAnnotationView {
override func prepareForReuse() {
- #if swift(>=3)
- isHidden = hideMarkerSwitchView.isOn
- #else
- hidden = hideMarkerSwitchView.on
- #endif
+ isHidden = hideMarkerSwitchView.isOn
}
}
@@ -86,8 +66,7 @@ class PlaygroundAnnotationView: MGLAnnotationView {
class MapDelegate: NSObject, MGLMapViewDelegate {
var annotationViewByAnnotation = [MGLPointAnnotation: PlaygroundAnnotationView]()
-
- #if swift(>=3)
+
func mapView(_ mapView: MGLMapView, viewFor annotation: MGLAnnotation) -> MGLAnnotationView? {
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "annotation") as? PlaygroundAnnotationView
@@ -109,31 +88,7 @@ class MapDelegate: NSObject, MGLMapViewDelegate {
return annotationView
}
- #else
- func mapView(mapView: MGLMapView, viewForAnnotation annotation: MGLAnnotation) -> MGLAnnotationView? {
-
- var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier("annotation") as? PlaygroundAnnotationView
-
- if (annotationView == nil) {
- let av = PlaygroundAnnotationView(reuseIdentifier: "annotation")
- av.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
- av.centerOffset = CGVector(dx: -15, dy: -15)
- let centerView = UIView(frame: CGRectInset(av.bounds, 3, 3))
- centerView.backgroundColor = UIColor.whiteColor()
- av.addSubview(centerView)
- av.backgroundColor = UIColor.purpleColor()
- annotationView = av
- } else {
- annotationView!.subviews.first?.backgroundColor = UIColor.greenColor()
- }
-
- annotationViewByAnnotation[annotation as! MGLPointAnnotation] = annotationView
-
- return annotationView
- }
- #endif
-
- #if swift(>=3)
+
func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) {
let pointAnnotation = annotation as! MGLPointAnnotation
let annotationView: PlaygroundAnnotationView = annotationViewByAnnotation[pointAnnotation]!
@@ -159,48 +114,14 @@ class MapDelegate: NSObject, MGLMapViewDelegate {
}
}
}
- #else
- func mapView(mapView: MGLMapView, didSelectAnnotation annotation: MGLAnnotation) {
- let pointAnnotation = annotation as! MGLPointAnnotation
- let annotationView: PlaygroundAnnotationView = annotationViewByAnnotation[pointAnnotation]!
-
- for view in annotationViewByAnnotation.values {
- view.layer.zPosition = -1
- }
-
- annotationView.layer.zPosition = 1
-
- UIView.animateWithDuration(1.25, delay: 0, usingSpringWithDamping: 0.4, initialSpringVelocity: 0.6, options: .CurveEaseOut, animations: {
- annotationView.transform = CGAffineTransformMakeScale(1.8, 1.8)
- }) { _ in
- annotationView.transform = CGAffineTransformMakeScale(1, 1)
-
- if deleteMarkerSwitchView.on {
- mapView.removeAnnotation(pointAnnotation)
- return
- }
-
- if hideMarkerSwitchView.on {
- annotationView.hidden = true
- }
- }
- }
- #endif
- func handleTap(press: UILongPressGestureRecognizer) {
+ @objc func handleTap(press: UILongPressGestureRecognizer) {
let mapView: MGLMapView = press.view as! MGLMapView
- #if swift(>=3)
- let isRecognized = press.state == .recognized
- #else
- let isRecognized = press.state == .Recognized
- #endif
+ let isRecognized = press.state == .recognized
+
if (isRecognized) {
- #if swift(>=3)
- let coordinate: CLLocationCoordinate2D = mapView.convert(press.location(in: mapView), toCoordinateFrom: mapView)
- #else
- let coordinate: CLLocationCoordinate2D = mapView.convertPoint(press.locationInView(mapView), toCoordinateFromView: mapView)
- #endif
+ let coordinate: CLLocationCoordinate2D = mapView.convert(press.location(in: mapView), toCoordinateFrom: mapView)
let annotation = MGLPointAnnotation()
annotation.title = "Dropped Marker"
annotation.coordinate = coordinate
@@ -218,11 +139,7 @@ let centerCoordinate = CLLocationCoordinate2D(latitude: 37.174057, longitude: -1
let mapView = MGLMapView(frame: CGRect(x: 0, y: 0, width: width, height: height))
mapView.frame = CGRect(x: 0, y: 0, width: width, height: height)
-#if swift(>=3)
- PlaygroundPage.current.liveView = mapView
-#else
- XCPlaygroundPage.currentPage.liveView = mapView
-#endif
+PlaygroundPage.current.liveView = mapView
let mapDelegate = MapDelegate()
mapView.delegate = mapDelegate
@@ -233,11 +150,7 @@ mapView.addGestureRecognizer(tapGesture)
//: Zoom in to a location
-#if swift(>=3)
- mapView.setCenter(centerCoordinate, zoomLevel: 12, animated: false)
-#else
- mapView.setCenterCoordinate(centerCoordinate, zoomLevel: 12, animated: false)
-#endif
+mapView.setCenter(centerCoordinate, zoomLevel: 12, animated: false)
//: Add control panel
diff --git a/platform/ios/Mapbox.playground/timeline.xctimeline b/platform/ios/Mapbox.playground/timeline.xctimeline
deleted file mode 100644
index bf468afeca..0000000000
--- a/platform/ios/Mapbox.playground/timeline.xctimeline
+++ /dev/null
@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<Timeline
- version = "3.0">
- <TimelineItems>
- </TimelineItems>
-</Timeline>
diff --git a/platform/ios/README.md b/platform/ios/README.md
index 3ca5b84dde..86474e1ea9 100644
--- a/platform/ios/README.md
+++ b/platform/ios/README.md
@@ -2,7 +2,7 @@
[![Bitrise](https://www.bitrise.io/app/7514e4cf3da2cc57.svg?token=OwqZE5rSBR9MVWNr_lf4sA&branch=master)](https://www.bitrise.io/app/7514e4cf3da2cc57)
-A library based on [Mapbox GL Native](../../README.md) for embedding interactive map views with scalable, customizable vector maps into Cocoa Touch applications on iOS 8.0 and above using Objective-C, Swift, or Interface Builder.
+A library based on [Mapbox GL Native](../../README.md) for embedding interactive map views with scalable, customizable vector maps into Cocoa Touch applications on iOS using Objective-C, Swift, or Interface Builder.
This repository is for day-to-day development of the SDK. Building the SDK yourself requires [a number of dependencies and steps](../../INSTALL.md) that are unnecessary for developing production applications. For production applications, please consider installing an official, prebuilt release instead; see the [Mapbox iOS SDK website](https://www.mapbox.com/ios-sdk/) for installation instructions.
diff --git a/platform/ios/app/MBXCustomCalloutView.m b/platform/ios/app/MBXCustomCalloutView.m
index 13564c5cbf..2d70e8b7b3 100644
--- a/platform/ios/app/MBXCustomCalloutView.m
+++ b/platform/ios/app/MBXCustomCalloutView.m
@@ -37,10 +37,9 @@ static CGFloat const tipWidth = 10.0;
return self;
}
-
#pragma mark - API
-- (void)presentCalloutFromRect:(CGRect)rect inView:(UIView *)view constrainedToView:(UIView *)constrainedView animated:(BOOL)animated
+- (void)presentCalloutFromRect:(CGRect)rect inView:(nonnull UIView *)view constrainedToRect:(__unused CGRect)constrainedRect animated:(BOOL)animated
{
if ([self.delegate respondsToSelector:@selector(calloutViewWillAppear:)])
{
@@ -108,5 +107,4 @@ static CGFloat const tipWidth = 10.0;
CGPathRelease(tipPath);
}
-
@end
diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m
index 6e31df384c..391af5ea05 100644
--- a/platform/ios/app/MBXViewController.m
+++ b/platform/ios/app/MBXViewController.m
@@ -54,6 +54,9 @@ typedef NS_ENUM(NSInteger, MBXSettingsAnnotationsRows) {
MBXSettingsAnnotationsQueryAnnotations,
MBXSettingsAnnotationsCustomUserDot,
MBXSettingsAnnotationsRemoveAnnotations,
+ MBXSettingsAnnotationSelectRandomOffscreenPointAnnotation,
+ MBXSettingsAnnotationCenterSelectedAnnotation,
+ MBXSettingsAnnotationAddVisibleAreaPolyline
};
typedef NS_ENUM(NSInteger, MBXSettingsRuntimeStylingRows) {
@@ -75,8 +78,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsRuntimeStylingRows) {
MBXSettingsRuntimeStylingUpdateShapeSourceData,
MBXSettingsRuntimeStylingUpdateShapeSourceURL,
MBXSettingsRuntimeStylingUpdateShapeSourceFeatures,
- MBXSettingsRuntimeStylingVectorSource,
- MBXSettingsRuntimeStylingRasterSource,
+ MBXSettingsRuntimeStylingVectorTileSource,
+ MBXSettingsRuntimeStylingRasterTileSource,
MBXSettingsRuntimeStylingImageSource,
MBXSettingsRuntimeStylingRouteLine,
MBXSettingsRuntimeStylingDDSPolygon,
@@ -89,7 +92,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
MBXSettingsMiscellaneousShowZoomLevel,
MBXSettingsMiscellaneousScrollView,
MBXSettingsMiscellaneousToggleTwoMaps,
- MBXSettingsMiscellaneousCountryLabels,
+ MBXSettingsMiscellaneousLocalizeLabels,
MBXSettingsMiscellaneousShowSnapshots,
MBXSettingsMiscellaneousShouldLimitCameraChanges,
MBXSettingsMiscellaneousPrintLogFile,
@@ -127,7 +130,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@property (nonatomic) NSInteger styleIndex;
@property (nonatomic) BOOL debugLoggingEnabled;
@property (nonatomic) BOOL customUserLocationAnnnotationEnabled;
-@property (nonatomic) BOOL usingLocaleBasedCountryLabels;
+@property (nonatomic, getter=isLocalizingLabels) BOOL localizingLabels;
@property (nonatomic) BOOL reuseQueueStatsEnabled;
@property (nonatomic) BOOL showZoomLevelEnabled;
@property (nonatomic) BOOL shouldLimitCameraChanges;
@@ -136,7 +139,6 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@interface MGLMapView (MBXViewController)
-@property (nonatomic) BOOL usingLocaleBasedCountryLabels;
@property (nonatomic) NSDictionary *annotationViewReuseQueueByIdentifier;
@end
@@ -171,9 +173,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
[self restoreState:nil];
self.debugLoggingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"MGLMapboxMetricsDebugLoggingEnabled"];
- self.mapView.scaleBar.hidden = NO;
+ self.mapView.showsScale = YES;
self.mapView.showsUserHeadingIndicator = YES;
- self.hudLabel.hidden = YES;
if ([UIFont respondsToSelector:@selector(monospacedDigitSystemFontOfSize:weight:)]) {
self.hudLabel.titleLabel.font = [UIFont monospacedDigitSystemFontOfSize:10 weight:UIFontWeightRegular];
}
@@ -223,6 +224,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
[defaults setInteger:self.mapView.userTrackingMode forKey:@"MBXUserTrackingMode"];
[defaults setBool:self.mapView.showsUserLocation forKey:@"MBXShowsUserLocation"];
[defaults setInteger:self.mapView.debugMask forKey:@"MBXDebugMask"];
+ [defaults setBool:self.showZoomLevelEnabled forKey:@"MBXShowsZoomLevelHUD"];
[defaults synchronize];
}
@@ -248,6 +250,11 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
{
self.mapView.debugMask = (MGLMapDebugMaskOptions)uncheckedDebugMask;
}
+ if ([defaults boolForKey:@"MBXShowsZoomLevelHUD"])
+ {
+ self.showZoomLevelEnabled = YES;
+ [self updateHUD];
+ }
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
@@ -335,6 +342,9 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@"Query Annotations",
[NSString stringWithFormat:@"%@ Custom User Dot", (_customUserLocationAnnnotationEnabled ? @"Disable" : @"Enable")],
@"Remove Annotations",
+ @"Select an offscreen point annotation",
+ @"Center selected annotation",
+ @"Add visible area polyline"
]];
break;
case MBXSettingsRuntimeStyling:
@@ -357,8 +367,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@"Update Shape Source: Data",
@"Update Shape Source: URL",
@"Update Shape Source: Features",
- @"Style Vector Source",
- @"Style Raster Source",
+ @"Style Vector Tile Source",
+ @"Style Raster Tile Source",
@"Style Image Source",
@"Add Route Line",
@"Dynamically Style Polygon",
@@ -372,7 +382,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
[NSString stringWithFormat:@"%@ Zoom/Pitch/Direction Label", (_showZoomLevelEnabled ? @"Hide" :@"Show")],
@"Embedded Map View",
[NSString stringWithFormat:@"%@ Second Map", ([self.view viewWithTag:2] == nil ? @"Show" : @"Hide")],
- [NSString stringWithFormat:@"Show Labels in %@", (_usingLocaleBasedCountryLabels ? @"Default Language" : [[NSLocale currentLocale] displayNameForKey:NSLocaleIdentifier value:[self bestLanguageForUser]])],
+ [NSString stringWithFormat:@"Show Labels in %@", (_localizingLabels ? @"Default Language" : [[NSLocale currentLocale] displayNameForKey:NSLocaleIdentifier value:[self bestLanguageForUser]])],
@"Show Snapshots",
[NSString stringWithFormat:@"%@ Camera Changes", (_shouldLimitCameraChanges ? @"Unlimit" : @"Limit")],
]];
@@ -463,6 +473,18 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
case MBXSettingsAnnotationsRemoveAnnotations:
[self.mapView removeAnnotations:self.mapView.annotations];
break;
+ case MBXSettingsAnnotationSelectRandomOffscreenPointAnnotation:
+ [self selectAnOffscreenPointAnnotation];
+ break;
+
+ case MBXSettingsAnnotationCenterSelectedAnnotation:
+ [self centerSelectedAnnotation];
+ break;
+
+ case MBXSettingsAnnotationAddVisibleAreaPolyline:
+ [self addVisibleAreaPolyline];
+ break;
+
default:
NSAssert(NO, @"All annotations setting rows should be implemented");
break;
@@ -525,11 +547,11 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
case MBXSettingsRuntimeStylingUpdateShapeSourceFeatures:
[self updateShapeSourceFeatures];
break;
- case MBXSettingsRuntimeStylingVectorSource:
- [self styleVectorSource];
+ case MBXSettingsRuntimeStylingVectorTileSource:
+ [self styleVectorTileSource];
break;
- case MBXSettingsRuntimeStylingRasterSource:
- [self styleRasterSource];
+ case MBXSettingsRuntimeStylingRasterTileSource:
+ [self styleRasterTileSource];
break;
case MBXSettingsRuntimeStylingImageSource:
[self styleImageSource];
@@ -551,7 +573,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
case MBXSettingsMiscellaneous:
switch (indexPath.row)
{
- case MBXSettingsMiscellaneousCountryLabels:
+ case MBXSettingsMiscellaneousLocalizeLabels:
[self styleCountryLabelsLanguage];
break;
case MBXSettingsMiscellaneousWorldTour:
@@ -945,18 +967,20 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@10.0f: [UIColor redColor],
@12.0f: [UIColor greenColor],
@14.0f: [UIColor blueColor]};
- waterLayer.fillColor = [NSExpression expressionWithFormat:
- @"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
- waterColorStops];
+ NSExpression *fillColorExpression = [NSExpression mgl_expressionForInterpolatingExpression:NSExpression.zoomLevelVariableExpression
+ withCurveType:MGLExpressionInterpolationModeLinear
+ parameters:nil
+ stops:[NSExpression expressionForConstantValue:waterColorStops]];
+ waterLayer.fillColor = fillColorExpression;
NSDictionary *fillAntialiasedStops = @{@11: @YES,
@12: @NO,
@13: @YES,
@14: @NO,
@15: @YES};
- waterLayer.fillAntialiased = [NSExpression expressionWithFormat:
- @"FUNCTION($zoomLevel, 'mgl_stepWithMinimum:stops:', false, %@)",
- fillAntialiasedStops];
+ waterLayer.fillAntialiased = [NSExpression mgl_expressionForSteppingExpression:NSExpression.zoomLevelVariableExpression
+ fromExpression:[NSExpression expressionForConstantValue:@NO]
+ stops:[NSExpression expressionForConstantValue:fillAntialiasedStops]];
}
- (void)styleRoadLayer
@@ -968,7 +992,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@10: @15,
@15: @30};
NSExpression *lineWidthExpression = [NSExpression expressionWithFormat:
- @"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
+ @"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)",
lineWidthStops];
roadLayer.lineWidth = lineWidthExpression;
roadLayer.lineGapWidth = lineWidthExpression;
@@ -977,7 +1001,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@13: [UIColor yellowColor],
@16: [UIColor cyanColor]};
roadLayer.lineColor = [NSExpression expressionWithFormat:
- @"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
+ @"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)",
roadLineColorStops];
roadLayer.visible = YES;
@@ -988,14 +1012,14 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
- (void)styleRasterLayer
{
NSURL *rasterURL = [NSURL URLWithString:@"mapbox://mapbox.satellite"];
- MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"my-raster-source" configurationURL:rasterURL tileSize:512];
- [self.mapView.style addSource:rasterSource];
+ MGLRasterTileSource *rasterTileSource = [[MGLRasterTileSource alloc] initWithIdentifier:@"my-raster-tile-source" configurationURL:rasterURL tileSize:512];
+ [self.mapView.style addSource:rasterTileSource];
- MGLRasterStyleLayer *rasterLayer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"my-raster-layer" source:rasterSource];
+ MGLRasterStyleLayer *rasterLayer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"my-raster-layer" source:rasterTileSource];
NSDictionary *opacityStops = @{@20.0f: @1.0f,
@5.0f: @0.0f};
rasterLayer.rasterOpacity = [NSExpression expressionWithFormat:
- @"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
+ @"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)",
opacityStops];
[self.mapView.style addLayer:rasterLayer];
}
@@ -1311,17 +1335,17 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
[self.mapView.style addLayer:layer];
}
-- (void)styleVectorSource
+- (void)styleVectorTileSource
{
NSURL *url = [[NSURL alloc] initWithString:@"mapbox://mapbox.mapbox-terrain-v2"];
- MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"style-vector-source-id" configurationURL:url];
- [self.mapView.style addSource:vectorSource];
+ MGLVectorTileSource *vectorTileSource = [[MGLVectorTileSource alloc] initWithIdentifier:@"style-vector-tile-source-id" configurationURL:url];
+ [self.mapView.style addSource:vectorTileSource];
MGLBackgroundStyleLayer *backgroundLayer = [[MGLBackgroundStyleLayer alloc] initWithIdentifier:@"style-vector-background-layer-id"];
backgroundLayer.backgroundColor = [NSExpression expressionForConstantValue:[UIColor blackColor]];
[self.mapView.style addLayer:backgroundLayer];
- MGLLineStyleLayer *lineLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"style-vector-line-layer-id" source:vectorSource];
+ MGLLineStyleLayer *lineLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"style-vector-line-layer-id" source:vectorTileSource];
lineLayer.sourceLayerIdentifier = @"contour";
lineLayer.lineJoin = [NSExpression expressionForConstantValue:@"round"];
lineLayer.lineCap = [NSExpression expressionForConstantValue:@"round"];
@@ -1330,15 +1354,15 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
[self.mapView.style addLayer:lineLayer];
}
-- (void)styleRasterSource
+- (void)styleRasterTileSource
{
NSString *tileURL = [NSString stringWithFormat:@"https://stamen-tiles.a.ssl.fastly.net/terrain-background/{z}/{x}/{y}%@.jpg", UIScreen.mainScreen.nativeScale > 1 ? @"@2x" : @""];
- MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"style-raster-source-id" tileURLTemplates:@[tileURL] options:@{
+ MGLRasterTileSource *rasterTileSource = [[MGLRasterTileSource alloc] initWithIdentifier:@"style-raster-tile-source-id" tileURLTemplates:@[tileURL] options:@{
MGLTileSourceOptionTileSize: @256,
}];
- [self.mapView.style addSource:rasterSource];
+ [self.mapView.style addSource:rasterTileSource];
- MGLRasterStyleLayer *rasterLayer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"style-raster-layer-id" source:rasterSource];
+ MGLRasterStyleLayer *rasterLayer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"style-raster-layer-id" source:rasterTileSource];
[self.mapView.style addLayer:rasterLayer];
}
@@ -1377,8 +1401,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
-(void)styleCountryLabelsLanguage
{
- _usingLocaleBasedCountryLabels = !_usingLocaleBasedCountryLabels;
- self.mapView.style.localizesLabels = _usingLocaleBasedCountryLabels;
+ _localizingLabels = !_localizingLabels;
+ [self.mapView.style localizeLabelsIntoLocale:_localizingLabels ? [NSLocale localeWithLocaleIdentifier:@"mul"] : nil];
}
- (void)styleRouteLine
@@ -1445,10 +1469,16 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
// source, categorical function that sets any feature with a "fill" attribute value of true to red color and anything without to green
MGLFillStyleLayer *fillStyleLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"fill-layer" source:shapeSource];
- fillStyleLayer.fillColor = [NSExpression expressionWithFormat:@"TERNARY(fill, %@, %@)", [UIColor greenColor], [UIColor redColor]];
+ fillStyleLayer.fillColor = [NSExpression mgl_expressionForConditional:[NSPredicate predicateWithFormat:@"fill == YES"]
+ trueExpression:[NSExpression expressionForConstantValue:[UIColor greenColor]]
+ falseExpresssion:[NSExpression expressionForConstantValue:[UIColor redColor]]];
+
+
// source, identity function that sets any feature with an "opacity" attribute to use that value and anything without to 1.0
- fillStyleLayer.fillOpacity = [NSExpression expressionWithFormat:@"TERNARY(opacity != nil, opacity, 1.0)"];
+ fillStyleLayer.fillOpacity = [NSExpression mgl_expressionForConditional:[NSPredicate predicateWithFormat:@"opacity != nil"]
+ trueExpression:[NSExpression expressionForKeyPath:@"opacity"]
+ falseExpresssion:[NSExpression expressionForConstantValue:@1.0]];
[self.mapView.style addLayer:fillStyleLayer];
}
@@ -1546,6 +1576,73 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
[self presentViewController:alertController animated:YES completion:nil];
}
+- (id<MGLAnnotation>)randomOffscreenPointAnnotation {
+
+ NSPredicate *pointAnnotationPredicate = [NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
+ return [evaluatedObject isKindOfClass:[MGLPointAnnotation class]];
+ }];
+
+ NSArray *annotations = [self.mapView.annotations filteredArrayUsingPredicate:pointAnnotationPredicate];
+
+ if (annotations.count == 0) {
+ return nil;
+ }
+
+ NSArray *visibleAnnotations = [self.mapView.visibleAnnotations filteredArrayUsingPredicate:pointAnnotationPredicate];
+
+ if (visibleAnnotations.count == annotations.count) {
+ return nil;
+ }
+
+ NSMutableArray *invisibleAnnotations = [annotations mutableCopy];
+
+ if (visibleAnnotations.count > 0) {
+ [invisibleAnnotations removeObjectsInArray:visibleAnnotations];
+ }
+
+ // Now pick a random offscreen annotation.
+ uint32_t index = arc4random_uniform((uint32_t)invisibleAnnotations.count);
+ return invisibleAnnotations[index];
+}
+
+- (void)selectAnOffscreenPointAnnotation {
+ id<MGLAnnotation> annotation = [self randomOffscreenPointAnnotation];
+ if (annotation) {
+ [self.mapView selectAnnotation:annotation animated:YES];
+
+ NSAssert(self.mapView.selectedAnnotations.firstObject, @"The annotation was not selected");
+ }
+}
+
+- (void)centerSelectedAnnotation {
+ id<MGLAnnotation> annotation = self.mapView.selectedAnnotations.firstObject;
+
+ if (!annotation)
+ return;
+
+ CGPoint point = [self.mapView convertCoordinate:annotation.coordinate toPointToView:self.mapView];
+
+ // Animate, so that point becomes the the center
+ CLLocationCoordinate2D center = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
+ [self.mapView setCenterCoordinate:center animated:YES];
+}
+
+- (void)addVisibleAreaPolyline {
+ CGRect constrainedRect = UIEdgeInsetsInsetRect(self.mapView.bounds, self.mapView.contentInset);
+
+ CLLocationCoordinate2D lineCoords[5];
+
+ lineCoords[0] = [self.mapView convertPoint: CGPointMake(CGRectGetMinX(constrainedRect), CGRectGetMinY(constrainedRect)) toCoordinateFromView:self.mapView];
+ lineCoords[1] = [self.mapView convertPoint: CGPointMake(CGRectGetMaxX(constrainedRect), CGRectGetMinY(constrainedRect)) toCoordinateFromView:self.mapView];
+ lineCoords[2] = [self.mapView convertPoint: CGPointMake(CGRectGetMaxX(constrainedRect), CGRectGetMaxY(constrainedRect)) toCoordinateFromView:self.mapView];
+ lineCoords[3] = [self.mapView convertPoint: CGPointMake(CGRectGetMinX(constrainedRect), CGRectGetMaxY(constrainedRect)) toCoordinateFromView:self.mapView];
+ lineCoords[4] = lineCoords[0];
+
+ MGLPolyline *line = [MGLPolyline polylineWithCoordinates:lineCoords
+ count:sizeof(lineCoords)/sizeof(lineCoords[0])];
+ [self.mapView addAnnotation:line];
+}
+
- (void)printTelemetryLogFile
{
NSString *fileContents = [NSString stringWithContentsOfFile:[self telemetryDebugLogFilePath] encoding:NSUTF8StringEncoding error:nil];
@@ -1597,7 +1694,13 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
toCoordinateFromView:self.mapView];
pin.title = title ?: @"Dropped Pin";
pin.subtitle = [[[MGLCoordinateFormatter alloc] init] stringFromCoordinate:pin.coordinate];
- // Calling `addAnnotation:` on mapView is not required since `selectAnnotation:animated` has the side effect of adding the annotation if required
+
+
+ // Calling `addAnnotation:` on mapView is required here (since `selectAnnotation:animated` has
+ // the side effect of adding the annotation if required, but returning an incorrect callout
+ // positioning rect)
+
+ [self.mapView addAnnotation:pin];
[self.mapView selectAnnotation:pin animated:YES];
}
}
@@ -1616,8 +1719,6 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@"Dark",
@"Satellite",
@"Satellite Streets",
- @"Traffic Day",
- @"Traffic Night",
];
styleURLs = @[
[MGLStyle streetsStyleURL],
@@ -1625,9 +1726,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
[MGLStyle lightStyleURL],
[MGLStyle darkStyleURL],
[MGLStyle satelliteStyleURL],
- [MGLStyle satelliteStreetsStyleURL],
- [NSURL URLWithString:@"mapbox://styles/mapbox/traffic-day-v2"],
- [NSURL URLWithString:@"mapbox://styles/mapbox/traffic-night-v2"],
+ [MGLStyle satelliteStreetsStyleURL]
];
NSAssert(styleNames.count == styleURLs.count, @"Style names and URLs don’t match.");
@@ -1718,12 +1817,6 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
// Comment out the pin dropping functionality in the handleLongPress:
// method in this class to make draggable annotation views play nice.
annotationView.draggable = YES;
-
- // Uncomment to force annotation view to maintain a constant size when
- // the map is tilted. By default, annotation views will shrink and grow
- // as they move towards and away from the horizon. Relatedly, annotations
- // backed by GL sprites currently ONLY scale with viewing distance.
- // annotationView.scalesWithViewingDistance = NO;
} else {
// orange indicates that the annotation view was reused
annotationView.backgroundColor = [UIColor orangeColor];
@@ -1898,7 +1991,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
// Default Mapbox styles use {name_en} as their label language, which means
// that a device with an English-language locale is already effectively
// using locale-based country labels.
- _usingLocaleBasedCountryLabels = [[self bestLanguageForUser] isEqualToString:@"en"];
+ _localizingLabels = [[self bestLanguageForUser] isEqualToString:@"en"];
}
- (BOOL)mapView:(MGLMapView *)mapView shouldChangeFromCamera:(MGLMapCamera *)oldCamera toCamera:(MGLMapCamera *)newCamera {
@@ -1943,6 +2036,8 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
- (void)updateHUD {
if (!self.reuseQueueStatsEnabled && !self.showZoomLevelEnabled) return;
+ if (self.hudLabel.hidden) self.hudLabel.hidden = NO;
+
NSString *hudString;
if (self.reuseQueueStatsEnabled) {
diff --git a/platform/ios/app/Main.storyboard b/platform/ios/app/Main.storyboard
index 507582213f..04e4f9ab45 100644
--- a/platform/ios/app/Main.storyboard
+++ b/platform/ios/app/Main.storyboard
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G8c" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="PSe-Ot-7Ff">
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="PSe-Ot-7Ff">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<deployment identifier="iOS"/>
- <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
<capability name="Constraints to layout margins" minToolsVersion="6.0"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
<capability name="Navigation items with more than one left or right bar item" minToolsVersion="7.0"/>
@@ -26,40 +26,44 @@
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kNe-zV-9ha" customClass="MGLMapView">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
+ <subviews>
+ <button hidden="YES" opaque="NO" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="58y-pX-YyB">
+ <rect key="frame" x="8" y="102" width="40" height="20"/>
+ <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
+ <accessibility key="accessibilityConfiguration">
+ <accessibilityTraits key="traits" button="YES" notEnabled="YES"/>
+ </accessibility>
+ <constraints>
+ <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="40" id="viz-kn-dfK"/>
+ <constraint firstAttribute="height" constant="20" id="zSU-Mb-f1v"/>
+ </constraints>
+ <fontDescription key="fontDescription" type="system" pointSize="10"/>
+ <inset key="contentEdgeInsets" minX="4" minY="2" maxX="4" maxY="2"/>
+ <userDefinedRuntimeAttributes>
+ <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
+ <integer key="value" value="2"/>
+ </userDefinedRuntimeAttribute>
+ </userDefinedRuntimeAttributes>
+ </button>
+ </subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<gestureRecognizers/>
+ <constraints>
+ <constraint firstItem="58y-pX-YyB" firstAttribute="top" secondItem="kNe-zV-9ha" secondAttribute="topMargin" constant="30" id="89S-qk-mPR"/>
+ <constraint firstItem="58y-pX-YyB" firstAttribute="leading" secondItem="kNe-zV-9ha" secondAttribute="leadingMargin" id="cXU-Qh-ilW"/>
+ <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="58y-pX-YyB" secondAttribute="trailing" id="txU-Gp-2du"/>
+ </constraints>
<connections>
<outlet property="delegate" destination="WaX-pd-UZQ" id="za0-3B-qR6"/>
<outletCollection property="gestureRecognizers" destination="lfd-mn-7en" appends="YES" id="0PH-gH-GRm"/>
</connections>
</view>
- <button opaque="NO" userInteractionEnabled="NO" alpha="0.69999999999999996" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="tailTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="58y-pX-YyB">
- <rect key="frame" x="319" y="606" width="40" height="21"/>
- <color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
- <accessibility key="accessibilityConfiguration">
- <accessibilityTraits key="traits" button="YES" notEnabled="YES"/>
- </accessibility>
- <constraints>
- <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="40" id="OL2-l5-I2f"/>
- <constraint firstAttribute="height" relation="greaterThanOrEqual" constant="20" id="xHg-ye-wzT"/>
- </constraints>
- <fontDescription key="fontDescription" type="system" pointSize="10"/>
- <inset key="contentEdgeInsets" minX="4" minY="2" maxX="4" maxY="2"/>
- <userDefinedRuntimeAttributes>
- <userDefinedRuntimeAttribute type="number" keyPath="layer.cornerRadius">
- <integer key="value" value="2"/>
- </userDefinedRuntimeAttribute>
- </userDefinedRuntimeAttributes>
- </button>
</subviews>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstItem="kNe-zV-9ha" firstAttribute="leading" secondItem="Z9X-fc-PUC" secondAttribute="leading" id="53e-Tz-QxF"/>
<constraint firstItem="kNe-zV-9ha" firstAttribute="bottom" secondItem="m8o-i7-QIy" secondAttribute="top" id="Etp-BC-E1N"/>
<constraint firstAttribute="trailing" secondItem="kNe-zV-9ha" secondAttribute="trailing" id="MGr-8G-VEb"/>
- <constraint firstItem="58y-pX-YyB" firstAttribute="trailing" secondItem="Z9X-fc-PUC" secondAttribute="trailingMargin" id="O3a-bR-boI"/>
- <constraint firstItem="58y-pX-YyB" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="Z9X-fc-PUC" secondAttribute="leadingMargin" id="ceH-yz-ewY"/>
- <constraint firstItem="m8o-i7-QIy" firstAttribute="top" secondItem="58y-pX-YyB" secondAttribute="bottom" constant="40" id="cjh-ZS-Mv4"/>
<constraint firstItem="kNe-zV-9ha" firstAttribute="top" secondItem="Z9X-fc-PUC" secondAttribute="top" id="qMm-e9-jxH"/>
</constraints>
</view>
@@ -133,14 +137,14 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="My Inactive Offline Pack" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="JtH-Ce-MI5">
- <rect key="frame" x="15" y="6" width="174.5" height="19.5"/>
+ <rect key="frame" x="16" y="6" width="174.5" height="19.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="456 resources (789 MB)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="tTJ-jv-U9v">
- <rect key="frame" x="15" y="25.5" width="128" height="13.5"/>
+ <rect key="frame" x="16" y="25.5" width="128.5" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -157,14 +161,14 @@
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="My Active Offline Pack" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="9ZK-gS-wJ4">
- <rect key="frame" x="15" y="6" width="163" height="19.5"/>
+ <rect key="frame" x="16" y="6" width="163" height="19.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Downloading 123 of 456 resources… (789 MB downloaded)" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="0xK-p8-Mmh">
- <rect key="frame" x="15" y="25.5" width="310.5" height="13.5"/>
+ <rect key="frame" x="16" y="25.5" width="311" height="13.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="11"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
@@ -201,7 +205,7 @@
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="PSe-Ot-7Ff" sceneMemberID="viewController">
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="ONr-CS-J5X">
- <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
+ <rect key="frame" x="0.0" y="20" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
diff --git a/platform/ios/app/da.lproj/Localizable.strings b/platform/ios/app/da.lproj/Localizable.strings
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/platform/ios/app/da.lproj/Localizable.strings
diff --git a/platform/ios/app/pt-PT.lproj/Localizable.strings b/platform/ios/app/pt-PT.lproj/Localizable.strings
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/platform/ios/app/pt-PT.lproj/Localizable.strings
diff --git a/platform/ios/docs/guides/Adding Markers to a Map.md b/platform/ios/docs/guides/Adding Markers to a Map.md
new file mode 100644
index 0000000000..b33b536d44
--- /dev/null
+++ b/platform/ios/docs/guides/Adding Markers to a Map.md
@@ -0,0 +1,62 @@
+# Adding Markers to a Map
+
+Mapbox offers a few different ways to add markers to a map, each with different tradeoffs. Below is an overview of the variety of approaches that can be used.
+
+## **Annotations API**
+
+Our annotations API includes the `MGLAnnotationImage`, and `MGLAnnotationView` classes. These are most similar to MapKit’s annotation class and provide a familiar interface for working with markers and callouts.
+
+| <img src="img/adding-points-to-a-map/annotation-image.png" alt="MGLAnnotationImage" style="height: 500px;"/> | <img src="img/adding-points-to-a-map/annotation-view.png" alt="MGLAnnotationView" style="height: 500px;"/> |
+|----------------------|---------------------|
+| `MGLAnnotationImage` | `MGLAnnotationView` |
+
+**MGLAnnotationImage** is an annotation class that is easily customizable with any `UIImage`.
+It is highly performant, as the images are rendered directly using OpenGL. However, if you need to animate your annotations or control z-layer ordering, consider working with **MGLAnnotationView** which supports any animation that can be applied to a `UIView`. View hierarchy can be manipulated by using instance methods available on `UIView` such as `-[UIView bringSubviewToFront:]`.
+
+**MGLAnnotationView** is an annotation class that is an easily customizable `UIView`. Use this class if you need your markers to be dynamic or animated. `MGLAnnotationView` has a significant advantage over `MGLAnnotationImage` when you need every annotation to be unique. For example, annotation views are ideal for showing user locations on a map using high-resolution profile pictures. However, the map can slow down when many annotation views are visible at the same time, so if you need to add a very large number of markers, consider using our runtime styling APIs instead.
+
+Both `MGLAnnotationImage` and `MGLAnnotationView` can become interactive by adding a [few lines of code](https://www.mapbox.com/ios-sdk/examples/marker/). When the user taps an annotation, the annotation’s name appears in a basic callout. An annotation view can additionally respond to [drag-and-drop gestures](https://www.mapbox.com/ios-sdk/examples/draggable-views/).
+
+## **Runtime styling API**
+
+For full control of how markers are displayed on a map, consider using our [runtime styling](runtime-styling.html) APIs. Like `MGLAnnotationImage`, it is a performant approach to adding markers because they rendered directly using OpenGL. However, the runtime styling APIs also provide support for rendering labels together with icons, finer control of z-ordering, and clustering, so consider using this set of APIs if you need to display a large amount of highly customizable markers.
+
+Our runtime styling API is the most powerful option if you need to create rich data visualizations within in your map, but it is the most complex and has a steeper learning curve than our annotations API.
+
+The runtime styling API includes our `MGLSymbolStyleLayer` and `MGLCircleStyleLayer` classes that can be used to dynamically display on markers on map when used in conjunction with either an `MGLVectorSource` or an `MGLShapeSource`.
+
+If you need to implement callouts with the `MGLSymbolStyleLayer` or `MGLCircleStyleLayer`, you will need to implement your own tap gesture recognizer that calls `-[MGLMapView visibleFeaturesAtPoint:inStyleLayersWithIdentifiers:]` to get the tapped point feature, then show a `UIView` you provide. Additionally, if you need to animate markers when using the runtime styling APIs, consider using a timer to update the source data coordinates accordingly.
+
+| <img src="img/adding-points-to-a-map/circle-layer.png" alt="MGLCircleStyleLayer" style="height: 500px;"/> | <img src="img/adding-points-to-a-map/symbol-layer.png" alt="MGLSymbolStyleLayer" style="height: 500px;"/> |
+|----------------------|---------------------|
+| `MGLCircleStyleLayer` | `MGLSymbolStyleLayer` |
+
+The **MGLCircleStyleLayer** class is the style layer class responsible for displaying the source’s point features as circle-shaped markers. You can specify circle fill and outline colors, as well as size. You can also dynamically change the circle’s styling properties based on any attributes your source data contains.
+
+The **MGLSymbolStyleLayer** class is the style layer class responsible for displaying the source’s point features as icons and labels. You can use custom images as icons and also combine text labels, placing them exactly where you specify. You can also dynamically change the symbol’s styling properties based on any attributes your source data contains.
+
+Still undecided on which approach will work best for your use case? [Reach out to our support team](https://www.mapbox.com/contact/).
+
+See the table below for a summary of APIs that can be used to add markers to a map:
+
+✅ Recommended
+
+⚠️ Supported with caveats
+
+➖ Unavailable or not supported
+
+
+| Feature | MGLAnnotationView | MGLAnnotationImage | MGLSymbolStyleLayer | MGLCircleStyleLayer |
+|----------------------------------------------------|--------------------------------------------------------------------|----------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------|
+| Customizability | ✅ Text labels, interactive subviews | ⚠️ Static images only | ✅ Full support for text labels and label placement | ✅Customize circle color and outline |
+| Borrows familiar concepts from | MapKit, Google Maps SDK | ➖ | Mapbox GL JS, Mapbox Studio | Mapbox GL JS, Mapbox Studio |
+| Can use images | ✅ | ✅ | ✅ | ➖ |
+| Can use text | ✅ | ➖ | ✅ | ➖ |
+| Control Z-index | ✅ | ➖ | ⚠️ Add multiple layers at, above, or below a specified layer index to control ordering | ⚠️ Add multiple layers at, above, or below a specified layer index to control ordering |
+| Drag and drop | ✅ | ➖ | ➖ | ➖ |
+| Core Animation support | ✅ | ➖ | ➖ | ➖ |
+| Add/move/replace data | ✅ | ✅ | ⚠️ Partial data updates are less performant than using annotations | ⚠️ Partial data updates are less performant than using annotations |
+| SceneKit support | ✅ | ➖ | ➖ | ➖ |
+| Can be dynamically styled based on data attributes | ✅ Subclass `MGLPointAnnotation` to add custom attributes | ✅ Subclass `MGLPointAnnotation` to add custom attributes | ✅ | ✅ |
+| Supports callouts | ✅ Built-in callouts included | ✅ Built-in callouts included | ⚠️ Implement your own gesture recognizer that uses feature querying, then create custom UIViews to mimic native callouts | ⚠️ Implement your own gesture recognizer that uses feature querying, then create custom UIViews to mimic native callouts |
+| Supports clustering | ⚠️ Use a [third-party plugin](https://github.com/hulab/ClusterKit/) | ➖ | ✅ | ✅ |
diff --git a/platform/ios/docs/guides/Adding Points to a Map.md b/platform/ios/docs/guides/Adding Points to a Map.md
deleted file mode 100644
index 2844075cc7..0000000000
--- a/platform/ios/docs/guides/Adding Points to a Map.md
+++ /dev/null
@@ -1,82 +0,0 @@
-# Adding Points to a Map
-
-Mapbox offers a few different ways to add points to a map, each with different tradeoffs.
-
-## MGLPointAnnotation
-
-It’s straightforward to add an annotation to a map. You can use `MGLPointAnnotation` as is, or you can subclass it to add annotations with richer data.
-
-```swift
-let annotation = MGLPointAnnotation()
-annotation.coordinate = CLLocationCoordinate2D(latitude: 45.5076, longitude: -122.6736)
-annotation.title = "Bobby's Coffee"
-annotation.subtitle = "Coffeeshop"
-mapView.addAnnotation(annotation)
-```
-
-See the `MGLMapViewDelegate` method `-mapView:annotationCanShowCallout:` and similar methods for allowing interaction with a callout ([example](https://www.mapbox.com/ios-sdk/examples/callout-delegate/)).
-
-## Displaying annotations
-
-There are two basic ways to display the annotations you’ve added to a map, each with their own tradeoffs.
-
-### Annotation Images (`MGLAnnotationImage`)
-
-Annotation images are the quickest and most performant way to display annotations, but are also the most basic.
-
-By default, annotations added to the map are displayed with a red pin ([example](https://www.mapbox.com/ios-sdk/examples/marker/)). To use custom images, you can implement `MGLMapViewDelegate` `-mapView:imageForAnnotation:` ([example](https://www.mapbox.com/ios-sdk/examples/marker-image/)).
-
-**Pros**
-
-* The easiest way to display a marker on a map
-* Easily customizable with any `UIImage`
-* High performance, as the images are rendered directly in OpenGL
-
-**Cons**
-
-* Annotation images are purely static and cannot be animated
-* No control over z-ordering
-
-### Annotation Views (`MGLAnnotationView`)
-
-If you’re looking to add custom `UIView`s or have annotations that are dynamic or animatable, consider an `MGLAnnotationView` instead of an `MGLAnnotationImage` ([example](https://www.mapbox.com/ios-sdk/examples/annotation-views/)).
-
-Annotation views have significant advantages over annotation images when you need every annotation to be unique. For example, annotation views are ideal for showing user locations on a map using high-resolution profile pictures.
-
-To use annotation views, implement `MGLMapViewDelegate` `-mapView:viewForAnnotation` and provide a custom `MGLAnnotationView` (`UIView`) subclass.
-
-**Pros**
-
-* Custom, native UIViews
-* No limit on style or image size
-* Full support for animations
-* Relative control over z-ordering using the `zPosition` property on `CALayer`
-* Familiar API for MapKit users
-
-**Cons**
-
-* Performance implications:
- * `UIView`s are inherently slow to render compared to OpenGL, more apparent if you’re adding many views or moving the map rapidly
- * In some cases, you might consider runtime styling
-
-## Advanced: Runtime Styling
-
-For absolute full control of how points are displayed on a map, consider [runtime styling](runtime-styling.html).
-
-You can use `MGLPointFeature` or any other [style primitives](Style%20Primitives.html) to add points and shapes to an `MGLShapeSource`.
-
-From there, you can create one or many `MGLSymbolStyleLayer` or `MGLCircleStyleLayer` layers to filter and style points for display on the map ([example](https://www.mapbox.com/ios-sdk/examples/runtime-multiple-annotations)).
-
-**Pros**
-
-* Most powerful option
-* Highest performance (rendered in GL directly)
-* SDK-level support for labels rendered together with icons
-* Finer control of z-ordering
- * Rendering respects ordering within the data source
- * Otherwise layers are lightweight so you can create a new layer for each level you need
-
-**Cons**
-
-* Currently you must implement your own tap gesture recognizer together with `MGLMapView.visibleFeaturesAtPoint` to recognize taps and manually show callouts ([example](https://www.mapbox.com/ios-sdk/examples/select-layer/)).
-* Currently no SDK support for animations. If you need animations, consider using an NSTimer and updating the layer properties accordingly.
diff --git a/platform/ios/docs/guides/For Style Authors.md b/platform/ios/docs/guides/For Style Authors.md
index c4aabb0410..b3beea8540 100644
--- a/platform/ios/docs/guides/For Style Authors.md
+++ b/platform/ios/docs/guides/For Style Authors.md
@@ -127,21 +127,22 @@ source object is a member of one of the following subclasses of `MGLSource`:
In style JSON | In the SDK
--------------|-----------
+`vector` | `MGLVectorTileSource`
+`raster` | `MGLRasterTileSource`
+`raster-dem` | `MGLRasterDEMSource`
`geojson` | `MGLShapeSource`
-`raster` | `MGLRasterSource`
-`vector` | `MGLVectorSource`
`image` | `MGLImageSource`
`canvas` and `video` sources are not supported.
### Tile sources
-Raster and vector sources may be defined in TileJSON configuration files. This
-SDK supports the properties defined in the style specification, which are a
+Raster and vector tile sources may be defined in TileJSON configuration files.
+This SDK supports the properties defined in the style specification, which are a
subset of the keys defined in version 2.1.0 of the
[TileJSON](https://github.com/mapbox/tilejson-spec/tree/master/2.1.0)
specification. As an alternative to authoring a custom TileJSON file, you may
-supply various tile source options when creating a raster or vector source.
+supply various tile source options when creating a raster or vector tile source.
These options are detailed in the `MGLTileSourceOption` documentation:
In style JSON | In TileJSON | In the SDK
@@ -311,6 +312,11 @@ defined by the style specification.
### Expression operators
+Many expression operators defined in the style specification have corresponding
+symbols to be used with the `+[NSExpression expressionWithFormat:]`,
+`+[NSExpression expressionForFunction:arguments:]`, or
+`+[NSExpression expressionForFunction:selectorName:arguments:]` method:
+
In style specification | Method, function, or predicate type | Format string syntax
-----------------------|-------------------------------------|---------------------
`array` | |
@@ -320,15 +326,15 @@ In style specification | Method, function, or predicate type | Format string syn
`string` | |
`to-boolean` | `boolValue` |
`to-color` | |
-`to-number` | `mgl_numberWithFallbackValues:` |
-`to-string` | `stringValue` |
+`to-number` | `mgl_numberWithFallbackValues:` | `CAST(zipCode, 'NSNumber')`
+`to-string` | `stringValue` | `CAST(ele, 'NSString')`
`typeof` | |
-`geometry-type` | |
-`id` | |
-`properties` | |
-`at` | |
+`geometry-type` | `NSExpression.geometryTypeVariableExpression` | `$geometryType`
+`id` | `NSExpression.featureIdentifierVariableExpression` | `$featureIdentifier`
+`properties` | `NSExpression.featureAttributesVariableExpression` | `$featureAttributes`
+`at` | `objectFrom:withIndex:` | `array[n]`
`get` | `+[NSExpression expressionForKeyPath:]` | Key path
-`has` | |
+`has` | `mgl_does:have:` | `mgl_does:have:(self, 'key')`
`length` | `count:` | `count({1, 2, 2, 3, 4, 7, 9})`
`!` | `NSNotPredicateType` | `NOT (p0 OR … OR pn)`
`!=` | `NSNotEqualToPredicateOperatorType` | `key != value`
@@ -339,17 +345,16 @@ In style specification | Method, function, or predicate type | Format string syn
`>=` | `NSGreaterThanOrEqualToPredicateOperatorType` | `key >= value`
`all` | `NSAndPredicateType` | `p0 AND … AND pn`
`any` | `NSOrPredicateType` | `p0 OR … OR pn`
-`case` | `+[NSExpression expressionForConditional:trueExpression:falseExpression:]` | `TERNARY(condition, trueExpression, falseExpression)`
-`coalesce` | |
-`match` | |
-`interpolate` | `mgl_interpolateWithCurveType:parameters:stops:` |
-`step` | `mgl_stepWithMinimum:stops:` |
-`let` | `mgl_expressionWithContext:` |
+`case` | `+[NSExpression expressionForConditional:trueExpression:falseExpression:]` or `MGL_IF` or `+[NSExpression mgl_expressionForConditional:trueExpression:falseExpresssion:]` | `TERNARY(1 = 2, YES, NO)` or `MGL_IF(1 = 2, YES, 2 = 2, YES, NO)`
+`coalesce` | `mgl_coalesce:` | `mgl_coalesce({x, y, z})`
+`match` | `MGL_MATCH` or `+[NSExpression mgl_expressionForMatchingExpression:inDictionary:defaultExpression:]` | `MGL_MATCH(x, 0, 'zero match', 1, 'one match', 'two match', 'default')`
+`interpolate` | `mgl_interpolate:withCurveType:parameters:stops:` or `+[NSExpression mgl_expressionForInterpolatingExpression:withCurveType:parameters:stops:]` |
+`step` | `mgl_step:withMinimum:stops:` or `+[NSExpression mgl_expressionForSteppingExpression:fromExpression:stops:]` |
+`let` | `mgl_expressionWithContext:` | `MGL_LET('ios', 11, 'macos', 10.13, $ios + $macos)`
`var` | `+[NSExpression expressionForVariable:]` | `$variable`
-`concat` | `stringByAppendingString:` |
+`concat` | `mgl_join:` or `-[NSExpression mgl_expressionByAppendingExpression:]` | `mgl_join({'Old', ' ', 'MacDonald'})`
`downcase` | `lowercase:` | `lowercase('DOWNTOWN')`
`upcase` | `uppercase:` | `uppercase('Elysian Fields')`
-
`rgb` | `+[UIColor colorWithRed:green:blue:alpha:]` |
`rgba` | `+[UIColor colorWithRed:green:blue:alpha:]` |
`to-rgba` | |
@@ -359,27 +364,34 @@ In style specification | Method, function, or predicate type | Format string syn
`%` | `modulus:by:` |
`^` | `raise:toPower:` | `2 ** 2`
`+` | `add:to:` | `1 + 2`
-`acos` | |
-`asin` | |
-`atan` | |
-`cos` | |
+`abs` | `abs:` | `abs(-1)`
+`acos` | `mgl_acos:` | `mgl_acos(1)`
+`asin` | `mgl_asin:` | `mgl_asin(0)`
+`atan` | `mgl_atan:` | `mgl_atan(20)`
+`ceil` | `ceiling:` | `ceiling(0.99999)`
+`cos` | `mgl_cos:` | `mgl_cos(0)`
`e` | | `%@` representing `NSNumber` containing `M_E`
+`floor` | `floor:` | `floor(-0.99999)`
`ln` | `ln:` | `ln(2)`
`ln2` | | `%@` representing `NSNumber` containing `M_LN2`
`log10` | `log:` | `log(1)`
-`log2` | |
+`log2` | `mgl_log2:` | `mgl_log2(1024)`
`max` | `max:` | `max({1, 2, 2, 3, 4, 7, 9})`
`min` | `min:` | `min({1, 2, 2, 3, 4, 7, 9})`
`pi` | | `%@` representing `NSNumber` containing `M_PI`
-`sin` | |
+`round` | `mgl_round:` | `mgl_round(1.5)`
+`sin` | `mgl_sin:` | `mgl_sin(0)`
`sqrt` | `sqrt:` | `sqrt(2)`
-`tan` | |
-`zoom` | | `$zoom`
-`heatmap-density` | | `$heatmapDensity`
+`tan` | `mgl_tan:` | `mgl_tan(0)`
+`zoom` | `NSExpression.zoomLevelVariableExpression` | `$zoom`
+`heatmap-density` | `NSExpression.heatmapDensityVariableExpression` | `$heatmapDensity`
+
+For operators that have no corresponding `NSExpression` symbol, use the
+`MGL_FUNCTION()` format string syntax.
## Filtering sources
-You can filter a shape or vector source by setting the
+You can filter a shape or vector tile source by setting the
`MGLVectorStyleLayer.predicate` property to an `NSPredicate` object. Below is a
table of style JSON operators and the corresponding operators used in the
predicate format string:
diff --git a/platform/ios/docs/guides/Info.plist Keys.md b/platform/ios/docs/guides/Info.plist Keys.md
index bc2f3f5786..cf00ec5499 100644
--- a/platform/ios/docs/guides/Info.plist Keys.md
+++ b/platform/ios/docs/guides/Info.plist Keys.md
@@ -8,7 +8,7 @@ Set the [Mapbox access token](https://www.mapbox.com/help/define-access-token/)
Mapbox-hosted vector tiles and styles require an API access token, which you can obtain from the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/). 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.
-As an alternative, you can use `+[MGLAccountManager setAccessToken:]` to set a token in code. See [our guide](https://www.mapbox.com/help/ios-private-access-token/) for some tips on keeping access tokens in open source code private.
+As an alternative, you can use `MGLAccountManager.accessToken` to set a token in code. See [our guide](https://www.mapbox.com/help/ios-private-access-token/) for some tips on keeping access tokens in open source code private.
## MGLMapboxAPIBaseURL
diff --git a/platform/ios/docs/guides/Migrating to Expressions.md b/platform/ios/docs/guides/Migrating to Expressions.md
new file mode 100644
index 0000000000..96d4df6853
--- /dev/null
+++ b/platform/ios/docs/guides/Migrating to Expressions.md
@@ -0,0 +1,266 @@
+<!--
+ This file is generated.
+ Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
+-->
+
+# Migrating from Style Functions to Expressions
+
+[Runtime Styling](runtime-styling.html) enables you to modify every aspect of the map’s appearance dynamically as a user interacts with your application. Developers can specify in advance how a layout or paint attribute will vary as the zoom level changes or how the appearance of individual features vary based on metadata provided by a content source.
+
+With Mapbox Maps SDK for iOS v4.0.0, style functions have been replaced with expressions. These provide even more tools for developers who want to style their maps dynamically. This guide outlines some tips for migrating from style functions to expressions, and offers an overview of some things that developers can do with expressions.
+
+An expression is represented at runtime by the `NSExpression` class. Expressions can be used to style paint and layout properties based on zoom level, data attributes, or a combination of the two.
+
+A constant expression can also be assigned to a style property. For example, the opacity of a fill style layer can be set to a constant value between 0 and 1.
+
+The documentation for each individual style layer property notes which non-constant expressions are enabled for that property. Style functions supported four interpolation modes: exponential, interval, categorical, and identity.
+
+This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php). Under each interpolation mode, the style function implementation will be shown, followed by the current syntax.
+
+For more information about how to work with GeoJSON data in our iOS SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide. To learn more about supported expressions, see our ["Predicates and Expressions"](predicates-and-expressions.html) guide. The "Predicates and Expressions" guide also outlines Mapbox custom functions that can be used to dynamically style a map.
+
+## Stops
+Stops are dictionary keys that are associated with layer attribute values. Constant values no longer need to be wrapped as style values when they are values in a stops dictionary.
+
+
+Style function syntax:
+
+```swift
+let stops = [
+ 0: MGLStyleValue<UIColor>(rawValue: .yellow),
+ 2.5: MGLStyleValue(rawValue: .orange),
+ 5: MGLStyleValue(rawValue: .red),
+ 7.5: MGLStyleValue(rawValue: .blue),
+ 10: MGLStyleValue(rawValue: .white),
+]
+```
+
+Current syntax:
+```swift
+let stops: [NSNumber: UIColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
+]
+```
+
+
+## Interpolation mode
+
+Style functions supported four interpolation modes: exponential/linear, interval, categorical, and identity. For more information about supported custom expressions, please see the "Predicates and Expressions" guide.
+
+### Linear
+
+`+[NSExpression(MGLAdditions) mgl_expressionForInterpolatingExpression:withCurveType:parameters:stops:]` takes the interpolation type as a parameter. If you previously used the default interpolation base, use the curve type `MGLExpressionInterpolationMode.linear`. See the [`mgl_interpolate:withCurveType:parameters:stops:`](predicates-and-expressions.html#code-mgl_interpolate-withcurvetype-parameters-stops-code) documentation for more details.
+
+The stops dictionary below, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value.
+
+Style function syntax:
+
+```swift
+let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
+let symbolSource = MGLSource(identifier: "source")
+let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbolSource)
+
+let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil)
+mapView.style?.addSource(source)
+
+let stops = [
+ 0: MGLStyleValue<UIColor>(rawValue: .yellow),
+ 2.5: MGLStyleValue(rawValue: .orange),
+ 5: MGLStyleValue(rawValue: .red),
+ 7.5: MGLStyleValue(rawValue: .blue),
+ 10: MGLStyleValue(rawValue: .white),
+]
+
+let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
+layer.circleColor = MGLStyleValue(interpolationMode: .exponential,
+ sourceStops: stops,
+ attributeName: "mag",
+ options: [.defaultValue: MGLStyleValue<UIColor>(rawValue: .green)])
+layer.circleRadius = MGLStyleValue(rawValue: 10)
+mapView.style?.insertLayer(layer, below: symbolLayer)
+```
+
+Current syntax:
+
+```swift
+let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
+let symbolSource = MGLSource(identifier: "source")
+let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbolSource)
+
+let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil)
+mapView.style?.addSource(source)
+
+let stops: [NSNumber: UIColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
+]
+
+let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
+layer.circleColor = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:(mag, 'linear', nil, %@)",
+ stops)
+layer.circleRadius = NSExpression(forConstantValue: 10)
+mapView.style?.insertLayer(layer, below: symbolLayer)
+```
+
+### Exponential
+
+If you previously used an interpolation base greater than `0` (other than `1`), you can use `MGLExpressionInterpolationMode.exponential` as the curve type for `+[NSExpression(MGLAdditions) mgl_expressionForInterpolatingExpression:withCurveType:parameters:stops:]` or `'exponential'` as the curve type for [`mgl_interpolate:withCurveType:parameters:stops:`](predicates-and-expressions.html#code-mgl_interpolate-withcurvetype-parameters-stops-code). The `parameters` argument takes that interpolation base. This interpolates between values exponentially, creating an accelerated ramp effect.
+
+Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom. In order to convert camera style functions, use `$zoomLevel` or `MGL_FUNCTION('zoomLevel')` as the attribute key.
+
+<img src="img/data-driven-styling/exponential-function.png" height=344/>
+<img src="img/data-driven-styling/exponential-function-1.png" height=344/>
+
+The example below increases a layer’s `circleRadius` exponentially based on a map’s zoom level. The interpolation base is `1.5`.
+
+Style function syntax:
+
+```swift
+let stops = [
+ 12: MGLStyleValue<NSNumber>(rawValue: 0.5),
+ 14: MGLStyleValue(rawValue: 2),
+ 18: MGLStyleValue(rawValue: 18),
+]
+
+layer.circleRadius = MGLStyleValue(interpolationMode: .exponential,
+ cameraStops: stops,
+ options: [.interpolationBase: 1.5])
+```
+
+Current syntax:
+
+```swift
+let stops = [
+ 12: 0.5,
+ 14: 2,
+ 18: 18,
+]
+
+layer.circleRadius = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'exponential', 1.5, %@)",
+ stops)
+```
+
+### Interval
+
+Steps, or intervals, create a range using the keys from the stops dictionary. The range is from the given key to just less than the next key. The attribute values that fall into that range are then styled using the layout or paint value assigned to that key. You can use the `+[NSExpression(MGLAdditions) mgl_expressionForSteppingExpression:fromExpression:stops:]` method or the custom function [`mgl_step:from:stops:`](predicates-and-expressions.html#code-mgl_step-from-stops-code) for cases where you previously used interval interpolation mode. The first parameter takes the feature attribute name and the second parameter (`from:`) optionally takes the default or fallback value for that function. The final parameter takes a stops dictionary as an argument.
+
+When we use the stops dictionary given above with an `'mgl_step:from:stops:'`, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on.
+
+Style function syntax:
+
+```swift
+let stops = [
+ 0: MGLStyleValue<UIColor>(rawValue: .yellow),
+ 2.5: MGLStyleValue(rawValue: .orange),
+ 5: MGLStyleValue(rawValue: .red),
+ 7.5: MGLStyleValue(rawValue: .blue),
+ 10: MGLStyleValue(rawValue: .white),
+]
+
+layer.circleColor = MGLStyleValue(interpolationMode: .interval,
+ sourceStops: stops,
+ attributeName: "mag",
+ options: [.defaultValue: MGLStyleValue<UIColor>(rawValue: .green)])
+````
+
+Current syntax:
+
+```swift
+let stops: [NSNumber: UIColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
+]
+
+layer.circleColor = NSExpression(format: "mgl_step:from:stops:(mag, %@, %@)",
+ UIColor.green, stops)
+```
+
+### Categorical
+
+Categorical interpolation mode took a stops dictionary. If the value for a specified feature attribute name matched one in that stops dictionary, the style value for that attribute value would be used. Categorical style functions can now be replaced with `MGL_MATCH`.
+
+`MGL_MATCH` takes an initial condition, which in this case is an attribute key. This is followed by possible matches for that key and the value to assign to the layer property if there is a match. The final argument can be a default style value that is to be used if none of the specified values match.
+
+There are three main types of events in the USGS dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of blue to catch any events that do not fall into any of those categories.
+
+Style function syntax:
+
+```swift
+let categoricalStops = [
+ "earthquake": MGLStyleValue<UIColor>(rawValue: .orange),
+ "explosion": MGLStyleValue(rawValue: .red),
+ "quarry blast": MGLStyleValue(rawValue: .yellow),
+]
+
+layer.circleColor = MGLStyleValue(interpolationMode: .categorical,
+ sourceStops: categoricalStops,
+ attributeName: "type",
+ options: [.defaultValue: MGLStyleValue<UIColor>(rawValue: .blue)])
+```
+
+Current syntax:
+```swift
+let defaultColor = UIColor.blue
+layer.circleColor = NSExpression(format: "MGL_MATCH(type, 'earthquake', %@, 'explosion', %@, 'quarry blast', %@, %@)",
+ UIColor.orange, UIColor.red, UIColor.yellow, defaultColor)
+```
+
+If your use case does not require a default value, you can either apply a predicate to your layer prior to styling it, or use the format string `"valueForKeyPath:"`.
+
+### Identity
+
+Identity interpolation mode used the attribute’s value as the style layer property value. In this example, you might set the `circleRadius` to the earthquake’s magnitude. In order to use a feature attribute value to style a layer property, set the property value to `[NSExpression expressionForKeyPath:]`, which take the feature attribute name as an argument.
+
+Style function syntax:
+
+```swift
+layer.circleRadius = MGLStyleValue(interpolationMode: .identity,
+ sourceStops: nil,
+ attributeName: "mag",
+ options: [.defaultValue: MGLStyleValue<NSNumber>(rawValue: 0)])
+```
+
+Current syntax:
+```swift
+layer.circleRadius = NSExpression(forKeyPath: "mag")
+```
+
+![identity mode](img/data-driven-styling/identity.png)
+
+Some built-in functions can be applied to attribute values to style layer property values. To set the circle radius to three times the earthquake’s magnitude, create a `multiply:by:` function that takes the attribute value and the multiplier as arguments, or use a format string.
+
+```swift
+layer.circleRadius = NSExpression(forFunction: "multiply:by:", arguments: [NSExpression(forKeyPath: "mag"), 3])
+```
+
+![multiply magnitude](img/data-driven-styling/multiply.png)
+
+You can also cast attribute values in order to use them. One example is to cast an integer as an `NSString` and use it as a text value.
+
+```swift
+let magnitudeLayer = MGLSymbolStyleLayer(identifier: "mag-layer", source: source)
+magnitudeLayer.text = NSExpression(format: "CAST(mag, 'NSString')")
+mapView.style?.addLayer(magnitudeLayer)
+```
+
+![cast a value](img/data-driven-styling/cast.png)
+
+### Constant Values
+
+For constant values that do not necessarily change based on camera or attribute values, use `[NSExpression expressionForConstantValue:]` (previously `[MGLStyleValue valueWithRawValue:]`).
+
+## Resources
+
+* [USGS Earthquake Feed](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php)
+* [For Style Authors](for-style-authors.html)
+* [Predicates and Expressions](predicates-and-expressions.html)
diff --git a/platform/ios/docs/guides/Tile URL Templates.md b/platform/ios/docs/guides/Tile URL Templates.md
index f61d2ea33a..4c8064f781 100644
--- a/platform/ios/docs/guides/Tile URL Templates.md
+++ b/platform/ios/docs/guides/Tile URL Templates.md
@@ -4,12 +4,12 @@
-->
# Tile URL Templates
-`MGLTileSource` objects, specifically `MGLRasterSource` and `MGLVectorSource`
-objects, can be created using an initializer that accepts an array of tile URL
-templates. Tile URL templates are strings that specify the URLs of the vector
-tiles or raster tile images to load. A template resembles an absolute URL, but
-with any number of placeholder strings that the source evaluates based on the
-tile it needs to load. For example:
+`MGLTileSource` objects, specifically `MGLRasterTileSource` and
+`MGLVectorTileSource` objects, can be created using an initializer that accepts
+an array of tile URL templates. Tile URL templates are strings that specify the
+URLs of the vector tiles or raster tile images to load. A template resembles an
+absolute URL, but with any number of placeholder strings that the source
+evaluates based on the tile it needs to load. For example:
* `http://www.example.com/tiles/{z}/{x}/{y}.pbf` could be
evaluated as `http://www.example.com/tiles/14/6/9.pbf`.
@@ -56,7 +56,7 @@ all of which are optional:
<td>The tile’s zoom level. At zoom level 0, each tile covers the entire
world map; at zoom level 1, it covers ¼ of the world; at zoom level 2,
<sup>1</sup>⁄<sub>16</sub> of the world, and so on. For tiles loaded by
- a <code>MGLRasterSource</code> object, whether the tile zoom level
+ a <code>MGLRasterTileSource</code> object, whether the tile zoom level
matches the map’s current zoom level depends on the value of the
source’s tile size as specified in the
<code>MGLTileSourceOptionTileSize</code> key of the <code>options</code>
diff --git a/platform/ios/docs/guides/Using Style Functions at Runtime.md b/platform/ios/docs/guides/Using Style Functions at Runtime.md
deleted file mode 100644
index 0b4e842e0e..0000000000
--- a/platform/ios/docs/guides/Using Style Functions at Runtime.md
+++ /dev/null
@@ -1,154 +0,0 @@
-<!--
- This file is generated.
- Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
--->
-
-# Using Style Functions at Runtime
-
-[Runtime Styling](runtime-styling.html) enables you to modify every aspect of the map’s appearance dynamically as a user interacts with your application. Much of the runtime styling API allows you to specify _style functions_ instead of constant values. A style function allows you to specify in advance how a layout or paint attribute will vary as the zoom level changes or how the appearance of individual features vary based on metadata provided by a content source.
-
-Style functions spare you the inconvenience of manually calculating intermediate values between different zoom levels or creating a multitude of style layers to handle homogeneous features in the map content. For example, if your content source indicates the prices of hotels in an area, you can color-code the hotels by price, relying on a style function to smoothly interpolate among desired colors without having to specify the color for each exact price.
-
-_Data-driven styling_ specifically refers to the use of style functions to vary the map’s appearance based on data in a content source.
-
-You can also specify style functions in a style JSON file, to be applied automatically when the map loads. See the [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-js/style-spec/#types-function) for details.
-
-![available bikes](img/data-driven-styling/citibikes.png) ![subway lines](img/data-driven-styling/polylineExample.png)
-
-This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) and data-driven styling to style a map based on attributes. For more information about how to work with GeoJSON data in our iOS SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide.
-
-A style function is represented at runtime by the `MGLStyleFunction` class. There are three subclasses of `MGLStyleFunction`:
-
-* `MGLCameraStyleFunction` is a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level.
-* `MGLSourceStyleFunction` is a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake.
-* `MGLCompositeStyleFunction` is a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake.
-
-The documentation for each individual style layer property notes which style functions are enabled for that property.
-
-## Stops
-
-Stops are dictionary keys that are associated with layer attribute values. With feature attribute values as stops, you can use a dictionary with a zoom level for a key and an expression or constant value for the value. For example, you can use a stop dictionary with the zoom levels 0, 10, and 20 as keys and the colors yellow, orange, and red as the values. Alternatively, attribute values can be the keys.
-
-```swift
-let stops: [Float: UIColor] = [
- 0: .yellow,
- 2.5: .orange,
- 5: .red,
- 7.5: .blue,
- 10: .white,
-]
-```
-
-## Interpolation mode
-
-The effect a key has on the style value is determined by the interpolation mode. There are four interpolation modes that can be used with a source style function: exponential, interval, categorical, and identity. You can also use exponential and interval interpolation modes with a camera style function.
-
-### Linear
-
-`MGLInterpolationModeExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation and doesn’t need to be included in the options dictionary.
-
-The stops dictionary below, for example, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value.
-
-```swift
-let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
-let symbolSource = MGLSource(identifier: "source")
-let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbolSource)
-
-let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil)
-mapView.style?.addSource(source)
-
-let stops: [Float: UIColor] = [
- 0: .yellow,
- 2.5: .orange,
- 5: .red,
- 7.5: .blue,
- 10: .white,
-]
-
-let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
-layer.circleColor = NSExpression(format: "FUNCTION(mag, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
- stops)
-layer.circleRadius = NSExpression(forConstantValue: 10)
-mapView.style?.insertLayer(layer, below: symbolLayer)
-```
-
-![exponential mode](img/data-driven-styling/exponential.png)
-
-### Exponential
-
-By combining `MGLInterpolationModeExponential` with an `MGLStyleFunctionOptionInterpolationBase` greater than `0` (other than `1`), you can interpolate between values exponentially, create an accelerated ramp effect.
-
-Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom.
-
-<img src="img/data-driven-styling/exponential-function.png" height=344/>
-<img src="img/data-driven-styling/exponential-function-1.png" height=344/>
-
-The example below increases a layer’s `circleRadius` exponentially based on a map’s zoom level. The `MGLStyleFunctionOptionInterpolationBase` is `1.5`.
-
-```swift
-let stops = [
- 12: 0.5,
- 14: 2,
- 18: 18,
-]
-
-layer.circleRadius = NSExpression(format: "FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'exponential', 1.5, %@)",
- stops)
-```
-
-### Interval
-
-`MGLInterpolationModeInterval` creates a range using the keys from the stops dictionary. The range is from the given key to just less than the next key. The attribute values that fall into that range are then styled using the style value assigned to that key.
-
-When we use the stops dictionary given above with an interval interpolation mode, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on.
-
-```swift
-let stops: [Float: UIColor] = [
- 0: .yellow,
- 2.5: .orange,
- 5: .red,
- 7.5: .blue,
- 10: .white,
-]
-
-layer.circleColor = NSExpression(format: "FUNCTION(mag, 'mgl_stepWithMinimum:stops:', %@, %@)",
- UIColor.green, stops)
-```
-
-![interval mode](img/data-driven-styling/interval.png)
-
-### Categorical
-
-At each stop, `MGLInterpolationModeCategorical` produces an output value equal to the function input. We’re going to use a different stops dictionary than we did for the previous two modes.
-
-There are three main types of events in the dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of blue to catch any events that do not fall into any of those categories.
-
-```swift
-let colors: [String: UIColor] = [
- "earthquake": .orange,
- "explosion": .red,
- "quarry blast": .yellow,
-]
-let defaultColor = UIColor.blue
-
-layer.circleColor = NSExpression(
- format: "TERNARY(FUNCTION(%@, 'valueForKeyPath:', type) != nil, FUNCTION(%@, 'valueForKeyPath:', type), %@)",
- colors, colors, defaultColor)
-```
-
-![categorical mode](img/data-driven-styling/categorical1.png) ![categorical mode](img/data-driven-styling/categorical2.png)
-
-### Identity
-
-`MGLInterpolationModeIdentity` uses the attribute’s value as the style value. For example, you can set the `circleRadius` to the earthquake’s magnitude. Since the attribute value itself will be used as the style value, `sourceStops` should be set to `nil`.
-
-```swift
-layer.circleRadius = NSExpression(forKeyPath: "mag")
-```
-
-![identity mode](img/data-driven-styling/identity.png)
-
-##Resources
-
-* [USGS](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php)
-* [For Style Authors](for-style-authors.html)
diff --git a/platform/ios/docs/img/adding-points-to-a-map/annotation-image.png b/platform/ios/docs/img/adding-points-to-a-map/annotation-image.png
new file mode 100644
index 0000000000..b9aa946363
--- /dev/null
+++ b/platform/ios/docs/img/adding-points-to-a-map/annotation-image.png
Binary files differ
diff --git a/platform/ios/docs/img/adding-points-to-a-map/annotation-view.png b/platform/ios/docs/img/adding-points-to-a-map/annotation-view.png
new file mode 100644
index 0000000000..90c181f664
--- /dev/null
+++ b/platform/ios/docs/img/adding-points-to-a-map/annotation-view.png
Binary files differ
diff --git a/platform/ios/docs/img/adding-points-to-a-map/circle-layer.png b/platform/ios/docs/img/adding-points-to-a-map/circle-layer.png
new file mode 100644
index 0000000000..5edf88e0da
--- /dev/null
+++ b/platform/ios/docs/img/adding-points-to-a-map/circle-layer.png
Binary files differ
diff --git a/platform/ios/docs/img/adding-points-to-a-map/symbol-layer.png b/platform/ios/docs/img/adding-points-to-a-map/symbol-layer.png
new file mode 100644
index 0000000000..cff39b0bce
--- /dev/null
+++ b/platform/ios/docs/img/adding-points-to-a-map/symbol-layer.png
Binary files differ
diff --git a/platform/ios/docs/img/runtime-styling/CustomAnnotations.gif b/platform/ios/docs/img/runtime-styling/CustomAnnotations.gif
index dee99d01fd..71d4c4a8a0 100644
--- a/platform/ios/docs/img/runtime-styling/CustomAnnotations.gif
+++ b/platform/ios/docs/img/runtime-styling/CustomAnnotations.gif
Binary files differ
diff --git a/platform/ios/docs/img/runtime-styling/DynamicStyles.gif b/platform/ios/docs/img/runtime-styling/DynamicStyles.gif
index b42d30c602..8854474ede 100644
--- a/platform/ios/docs/img/runtime-styling/DynamicStyles.gif
+++ b/platform/ios/docs/img/runtime-styling/DynamicStyles.gif
Binary files differ
diff --git a/platform/ios/docs/img/runtime-styling/Emoji.gif b/platform/ios/docs/img/runtime-styling/Emoji.gif
index fc50b28972..afb7a42693 100644
--- a/platform/ios/docs/img/runtime-styling/Emoji.gif
+++ b/platform/ios/docs/img/runtime-styling/Emoji.gif
Binary files differ
diff --git a/platform/ios/docs/img/runtime-styling/HexBins.gif b/platform/ios/docs/img/runtime-styling/HexBins.gif
index c810085f22..6078ac9e8d 100644
--- a/platform/ios/docs/img/runtime-styling/HexBins.gif
+++ b/platform/ios/docs/img/runtime-styling/HexBins.gif
Binary files differ
diff --git a/platform/ios/docs/img/runtime-styling/Population.gif b/platform/ios/docs/img/runtime-styling/Population.gif
index 81b6c6310f..8de14e6422 100644
--- a/platform/ios/docs/img/runtime-styling/Population.gif
+++ b/platform/ios/docs/img/runtime-styling/Population.gif
Binary files differ
diff --git a/platform/ios/docs/img/runtime-styling/SnowLevels.gif b/platform/ios/docs/img/runtime-styling/SnowLevels.gif
index 8ee2f9fddd..463e0398d2 100644
--- a/platform/ios/docs/img/runtime-styling/SnowLevels.gif
+++ b/platform/ios/docs/img/runtime-styling/SnowLevels.gif
Binary files differ
diff --git a/platform/ios/docs/img/studio-workflow/add-properties.gif b/platform/ios/docs/img/studio-workflow/add-properties.gif
index 740fae655b..6cab64c050 100644
--- a/platform/ios/docs/img/studio-workflow/add-properties.gif
+++ b/platform/ios/docs/img/studio-workflow/add-properties.gif
Binary files differ
diff --git a/platform/ios/docs/img/studio-workflow/create-polygons.gif b/platform/ios/docs/img/studio-workflow/create-polygons.gif
index 6eb2c0afb8..6383dd31df 100644
--- a/platform/ios/docs/img/studio-workflow/create-polygons.gif
+++ b/platform/ios/docs/img/studio-workflow/create-polygons.gif
Binary files differ
diff --git a/platform/ios/docs/img/studio-workflow/property-values.png b/platform/ios/docs/img/studio-workflow/property-values.png
index 95704241f9..2b85db80d6 100644
--- a/platform/ios/docs/img/studio-workflow/property-values.png
+++ b/platform/ios/docs/img/studio-workflow/property-values.png
Binary files differ
diff --git a/platform/ios/docs/img/studio-workflow/stop-functions.png b/platform/ios/docs/img/studio-workflow/stop-functions.png
index 4affecf005..8480cb2d53 100644
--- a/platform/ios/docs/img/studio-workflow/stop-functions.png
+++ b/platform/ios/docs/img/studio-workflow/stop-functions.png
Binary files differ
diff --git a/platform/ios/framework/Settings.bundle/ca.lproj/Root.strings b/platform/ios/framework/Settings.bundle/ca.lproj/Root.strings
index 94e8335582..3f6104a075 100644
--- a/platform/ios/framework/Settings.bundle/ca.lproj/Root.strings
+++ b/platform/ios/framework/Settings.bundle/ca.lproj/Root.strings
@@ -1,3 +1,3 @@
-"TELEMETRY_GROUP_TITLE" = "Configuració de privacitat";
+"TELEMETRY_GROUP_TITLE" = "Configuració de privacitat";
"TELEMETRY_SWITCH_TITLE" = "Telemetria Mapbox";
"TELEMETRY_GROUP_FOOTER" = "Aquest ajust permet que l’aplicació comparteixi dades anònimes de localització i ús amb Mapbox.";
diff --git a/platform/ios/framework/Settings.bundle/da.lproj/Root.strings b/platform/ios/framework/Settings.bundle/da.lproj/Root.strings
new file mode 100644
index 0000000000..b1129a865a
--- /dev/null
+++ b/platform/ios/framework/Settings.bundle/da.lproj/Root.strings
@@ -0,0 +1,3 @@
+"TELEMETRY_GROUP_TITLE" = "Privatlivs indstillinger";
+"TELEMETRY_SWITCH_TITLE" = "Mapbox Telemetry";
+"TELEMETRY_GROUP_FOOTER" = "Denne indstilling giver app'en tilladelse til at dele anonyme bruger data og position med Mapbox.";
diff --git a/platform/ios/framework/Settings.bundle/de.lproj/Root.strings b/platform/ios/framework/Settings.bundle/de.lproj/Root.strings
index c57189d4af..30bd2252ce 100644
--- a/platform/ios/framework/Settings.bundle/de.lproj/Root.strings
+++ b/platform/ios/framework/Settings.bundle/de.lproj/Root.strings
@@ -1,3 +1,3 @@
-"TELEMETRY_GROUP_TITLE" = "Privatsphäre-Einstellungen";
+"TELEMETRY_GROUP_TITLE" = "Privatsphäre-Einstellungen";
"TELEMETRY_SWITCH_TITLE" = "Mapbox-Telemetrie";
"TELEMETRY_GROUP_FOOTER" = "Diese Einstellung erlaubt der Applikation, anonymisierte Orts- und Nutzungsdaten an Mapbox zu senden.";
diff --git a/platform/ios/framework/Settings.bundle/es.lproj/Root.strings b/platform/ios/framework/Settings.bundle/es.lproj/Root.strings
index bb0c52dcde..48da358189 100644
--- a/platform/ios/framework/Settings.bundle/es.lproj/Root.strings
+++ b/platform/ios/framework/Settings.bundle/es.lproj/Root.strings
@@ -1,3 +1,3 @@
-"TELEMETRY_GROUP_TITLE" = "Ajustes de privacidad";
+"TELEMETRY_GROUP_TITLE" = "Ajustes de privacidad";
"TELEMETRY_SWITCH_TITLE" = "Telemetría Mapbox";
"TELEMETRY_GROUP_FOOTER" = "Esta configuración permite que la aplicación comparta datos anónimos de ubicación y uso con Mapbox.";
diff --git a/platform/ios/framework/Settings.bundle/fi.lproj/Root.strings b/platform/ios/framework/Settings.bundle/fi.lproj/Root.strings
index e0c2e50d09..b12a017e8a 100644
--- a/platform/ios/framework/Settings.bundle/fi.lproj/Root.strings
+++ b/platform/ios/framework/Settings.bundle/fi.lproj/Root.strings
@@ -1,3 +1,3 @@
-"TELEMETRY_GROUP_TITLE" = "Yksityisyysasetukset";
+"TELEMETRY_GROUP_TITLE" = "Yksityisyysasetukset";
"TELEMETRY_SWITCH_TITLE" = "Mapbox-telemetria";
"TELEMETRY_GROUP_FOOTER" = "Tämä asetus antaa sovellukselle luvan jakaa anonymisoituja sijainti- ja käyttötietoja Mapboxille.";
diff --git a/platform/ios/framework/Settings.bundle/fr.lproj/Root.strings b/platform/ios/framework/Settings.bundle/fr.lproj/Root.strings
index c386d9846d..f00e8e2fe8 100644
--- a/platform/ios/framework/Settings.bundle/fr.lproj/Root.strings
+++ b/platform/ios/framework/Settings.bundle/fr.lproj/Root.strings
@@ -1,3 +1,3 @@
-"TELEMETRY_GROUP_TITLE" = "Paramètres de confidentialité";
+"TELEMETRY_GROUP_TITLE" = "Paramètres de confidentialité";
"TELEMETRY_SWITCH_TITLE" = "Télémétrie Mapbox";
"TELEMETRY_GROUP_FOOTER" = "Cette option permet à l’application de partager des données de localisation et d’utilisation anonymes avec Mapbox.";
diff --git a/platform/ios/framework/Settings.bundle/lt.lproj/Root.strings b/platform/ios/framework/Settings.bundle/lt.lproj/Root.strings
index 832b16608b..5ae715439a 100644
--- a/platform/ios/framework/Settings.bundle/lt.lproj/Root.strings
+++ b/platform/ios/framework/Settings.bundle/lt.lproj/Root.strings
@@ -1,3 +1,3 @@
-"TELEMETRY_GROUP_TITLE" = "Privatumo nustatymai";
+"TELEMETRY_GROUP_TITLE" = "Privatumo nustatymai";
"TELEMETRY_SWITCH_TITLE" = "Mapbox Telemetrija";
"TELEMETRY_GROUP_FOOTER" = "Šis nustatymas leidžia programėlei dalintis su Mapbox anonimizuota lokacija bei naudojimosi duomenimis.";
diff --git a/platform/ios/framework/Settings.bundle/nl.lproj/Root.strings b/platform/ios/framework/Settings.bundle/nl.lproj/Root.strings
index ea73b0ba3c..9f09002349 100644
--- a/platform/ios/framework/Settings.bundle/nl.lproj/Root.strings
+++ b/platform/ios/framework/Settings.bundle/nl.lproj/Root.strings
@@ -1,3 +1,3 @@
-"TELEMETRY_GROUP_TITLE" = "Privacy Instellingen";
+"TELEMETRY_GROUP_TITLE" = "Privacy Instellingen";
"TELEMETRY_SWITCH_TITLE" = "Mapbox Telemetrie";
"TELEMETRY_GROUP_FOOTER" = "Deze instelling laat toe om anonieme locatie en gebruiksgegevens te delen met Mapbox.";
diff --git a/platform/ios/framework/Settings.bundle/pl.lproj/Root.strings b/platform/ios/framework/Settings.bundle/pl.lproj/Root.strings
index 4cf2c71381..f273a15293 100644
--- a/platform/ios/framework/Settings.bundle/pl.lproj/Root.strings
+++ b/platform/ios/framework/Settings.bundle/pl.lproj/Root.strings
@@ -1,3 +1,3 @@
-"TELEMETRY_GROUP_TITLE" = "Ustawienia prywatności";
+"TELEMETRY_GROUP_TITLE" = "Ustawienia prywatności";
"TELEMETRY_SWITCH_TITLE" = "Mapbox Telemetria";
"TELEMETRY_GROUP_FOOTER" = "Ta opcja pozwala aplikacji na anonimowe wysyłanie lokalizacji i danych do Mapbox.";
diff --git a/platform/ios/framework/Settings.bundle/pt-BR.lproj/Root.strings b/platform/ios/framework/Settings.bundle/pt-BR.lproj/Root.strings
index 5b81fb66eb..f96fadd205 100644
--- a/platform/ios/framework/Settings.bundle/pt-BR.lproj/Root.strings
+++ b/platform/ios/framework/Settings.bundle/pt-BR.lproj/Root.strings
@@ -1,3 +1,3 @@
-"TELEMETRY_GROUP_TITLE" = "Configurações de privacidade";
+"TELEMETRY_GROUP_TITLE" = "Configurações de privacidade";
"TELEMETRY_SWITCH_TITLE" = "Telemetria do Mapbox";
"TELEMETRY_GROUP_FOOTER" = "Essa configuração permite que o aplicativo compartilhe dados de localização e uso anônimos com o Mapbox.";
diff --git a/platform/ios/framework/Settings.bundle/pt-PT.lproj/Root.strings b/platform/ios/framework/Settings.bundle/pt-PT.lproj/Root.strings
new file mode 100644
index 0000000000..8e077c3d1f
--- /dev/null
+++ b/platform/ios/framework/Settings.bundle/pt-PT.lproj/Root.strings
@@ -0,0 +1,3 @@
+"TELEMETRY_GROUP_TITLE" = "Definições de Privacidade";
+"TELEMETRY_SWITCH_TITLE" = "Telemetria Mapbox";
+"TELEMETRY_GROUP_FOOTER" = "Esta definição permite à aplicação partilhar a localização e dados de utilização tornados anónimos com a Mapbox.";
diff --git a/platform/ios/framework/Settings.bundle/ru.lproj/Root.strings b/platform/ios/framework/Settings.bundle/ru.lproj/Root.strings
index 2883ec4b87..3e37d64126 100644
--- a/platform/ios/framework/Settings.bundle/ru.lproj/Root.strings
+++ b/platform/ios/framework/Settings.bundle/ru.lproj/Root.strings
@@ -1,3 +1,3 @@
-"TELEMETRY_GROUP_TITLE" = "Настройки приватности";
-"TELEMETRY_SWITCH_TITLE" = "Mapbox Телеметрия";
-"TELEMETRY_GROUP_FOOTER" = "Эта настройка разрешает приложению отправлять анонимную позицию и данные об использовании в Mapbox";
+"TELEMETRY_GROUP_TITLE" = "Настройки приватности";
+"TELEMETRY_SWITCH_TITLE" = "Телеметрия Mapbox";
+"TELEMETRY_GROUP_FOOTER" = "Эта настройка разрешает приложению отправлять обезличенные данные об использовании и местоположении в Mapbox.";
diff --git a/platform/ios/framework/Settings.bundle/sv.lproj/Root.strings b/platform/ios/framework/Settings.bundle/sv.lproj/Root.strings
index f8324c14c4..e771af505a 100644
--- a/platform/ios/framework/Settings.bundle/sv.lproj/Root.strings
+++ b/platform/ios/framework/Settings.bundle/sv.lproj/Root.strings
@@ -1,3 +1,3 @@
-"TELEMETRY_GROUP_TITLE" = "Sekretessinställningar";
+"TELEMETRY_GROUP_TITLE" = "Sekretessinställningar";
"TELEMETRY_SWITCH_TITLE" = "Mapbox Telemetri";
"TELEMETRY_GROUP_FOOTER" = "Denna inställning tillåter applikationen att dela anonymiserad plats och användningsdata med Mapbox.";
diff --git a/platform/ios/framework/Settings.bundle/uk.lproj/Root.strings b/platform/ios/framework/Settings.bundle/uk.lproj/Root.strings
index 5d2bfd648e..b1615849f6 100644
--- a/platform/ios/framework/Settings.bundle/uk.lproj/Root.strings
+++ b/platform/ios/framework/Settings.bundle/uk.lproj/Root.strings
@@ -1,3 +1,3 @@
-"TELEMETRY_GROUP_TITLE" = "Налаштування конфіденційності";
+"TELEMETRY_GROUP_TITLE" = "Налаштування конфіденційності";
"TELEMETRY_SWITCH_TITLE" = "Телеметрія Mapbox";
"TELEMETRY_GROUP_FOOTER" = "Ці налаштування дозволяють застосунку надсилати анонімізовані дані про місце знаходження та використання даних до Mapbox.";
diff --git a/platform/ios/framework/Settings.bundle/vi.lproj/Root.strings b/platform/ios/framework/Settings.bundle/vi.lproj/Root.strings
index e156d9937a..29060d00a4 100644
--- a/platform/ios/framework/Settings.bundle/vi.lproj/Root.strings
+++ b/platform/ios/framework/Settings.bundle/vi.lproj/Root.strings
@@ -1,3 +1,3 @@
-"TELEMETRY_GROUP_TITLE" = "Thiết lập Quyền riêng tư";
+"TELEMETRY_GROUP_TITLE" = "Thiết lập Quyền riêng tư";
"TELEMETRY_SWITCH_TITLE" = "Trình viễn trắc Mapbox";
"TELEMETRY_GROUP_FOOTER" = "Tùy chọn này cho phép ứng dụng gửi cho Mapbox các vị trí và dữ liệu sử dụng được vô danh hóa.";
diff --git a/platform/ios/framework/Settings.bundle/zh-Hans.lproj/Root.strings b/platform/ios/framework/Settings.bundle/zh-Hans.lproj/Root.strings
index 3cfb1a4bad..b9e1a98325 100644
--- a/platform/ios/framework/Settings.bundle/zh-Hans.lproj/Root.strings
+++ b/platform/ios/framework/Settings.bundle/zh-Hans.lproj/Root.strings
@@ -1,3 +1,3 @@
-"TELEMETRY_GROUP_TITLE" = "隐私设置";
+"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 07fae5945c..a9413accf2 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -15,11 +15,8 @@
0778DD431F67556700A73B34 /* MGLComputedShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 0778DD401F67555F00A73B34 /* MGLComputedShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
0778DD441F67556C00A73B34 /* MGLComputedShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0778DD411F67555F00A73B34 /* MGLComputedShapeSource.mm */; };
07D8C6FB1F67560100381808 /* MGLComputedShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0778DD411F67555F00A73B34 /* MGLComputedShapeSource.mm */; };
- 07D8C6FC1F67560400381808 /* MGLAbstractShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07D947501F67487E00E37934 /* MGLAbstractShapeSource.mm */; };
07D8C6FF1F67562C00381808 /* MGLComputedShapeSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 07D8C6FD1F67562800381808 /* MGLComputedShapeSourceTests.m */; };
- 07D947521F67488800E37934 /* MGLAbstractShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D9474F1F67487E00E37934 /* MGLAbstractShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 07D947531F67488E00E37934 /* MGLAbstractShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D9474E1F67487E00E37934 /* MGLAbstractShapeSource_Private.h */; };
- 07D947541F67489200E37934 /* MGLAbstractShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07D947501F67487E00E37934 /* MGLAbstractShapeSource.mm */; };
+ 07D947531F67488E00E37934 /* MGLComputedShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D9474E1F67487E00E37934 /* MGLComputedShapeSource_Private.h */; };
16376B0A1FFD9DAF0000563E /* MBGLIntegrationTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 16376B091FFD9DAF0000563E /* MBGLIntegrationTests.m */; };
16376B331FFDB4B40000563E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 16376B321FFDB4B40000563E /* AppDelegate.m */; };
16376B3B1FFDB4B40000563E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 16376B3A1FFDB4B40000563E /* Assets.xcassets */; };
@@ -27,7 +24,6 @@
16376B411FFDB4B40000563E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 16376B401FFDB4B40000563E /* main.m */; };
16376B471FFDB92B0000563E /* one-liner.json in Resources */ = {isa = PBXBuildFile; fileRef = DA35D0871E1A6309007DED41 /* one-liner.json */; };
16376B491FFEED010000563E /* MGLMapViewLayoutTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 16376B481FFEED010000563E /* MGLMapViewLayoutTests.m */; };
- 165D0CE720005419009A3C66 /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA8847D21CBAF91600AB86E3 /* Mapbox.framework */; };
170C437C2029D96F00863DF0 /* MGLHeatmapColorTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 170C43782028D49800863DF0 /* MGLHeatmapColorTests.mm */; };
170C437D2029D97900863DF0 /* MGLHeatmapStyleLayerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 170C43792028D49800863DF0 /* MGLHeatmapStyleLayerTests.mm */; };
1753ED421E53CE6F00A9FD90 /* MGLConversion.h in Headers */ = {isa = PBXBuildFile; fileRef = 1753ED411E53CE6F00A9FD90 /* MGLConversion.h */; };
@@ -44,10 +40,10 @@
30E578181DAA85520050F07E /* UIImage+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30E578111DAA7D690050F07E /* UIImage+MGLAdditions.h */; };
30E578191DAA855E0050F07E /* UIImage+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 30E578121DAA7D690050F07E /* UIImage+MGLAdditions.mm */; };
30E5781A1DAA855E0050F07E /* UIImage+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 30E578121DAA7D690050F07E /* UIImage+MGLAdditions.mm */; };
- 350098BB1D480108004B2AF0 /* MGLVectorSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 350098B91D480108004B2AF0 /* MGLVectorSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 350098BC1D480108004B2AF0 /* MGLVectorSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 350098B91D480108004B2AF0 /* MGLVectorSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 350098BD1D480108004B2AF0 /* MGLVectorSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 350098BA1D480108004B2AF0 /* MGLVectorSource.mm */; };
- 350098BE1D480108004B2AF0 /* MGLVectorSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 350098BA1D480108004B2AF0 /* MGLVectorSource.mm */; };
+ 350098BB1D480108004B2AF0 /* MGLVectorTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 350098B91D480108004B2AF0 /* MGLVectorTileSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 350098BC1D480108004B2AF0 /* MGLVectorTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 350098B91D480108004B2AF0 /* MGLVectorTileSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 350098BD1D480108004B2AF0 /* MGLVectorTileSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 350098BA1D480108004B2AF0 /* MGLVectorTileSource.mm */; };
+ 350098BE1D480108004B2AF0 /* MGLVectorTileSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 350098BA1D480108004B2AF0 /* MGLVectorTileSource.mm */; };
350098DC1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 350098DA1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h */; };
350098DD1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 350098DA1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h */; };
350098DE1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 350098DB1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm */; };
@@ -57,7 +53,7 @@
3510FFEC1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3510FFE91D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm */; };
3510FFED1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3510FFE91D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm */; };
3510FFF01D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3510FFEE1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 3510FFF11D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3510FFEE1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h */; };
+ 3510FFF11D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3510FFEE1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
3510FFF21D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3510FFEF1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm */; };
3510FFF31D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3510FFEF1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm */; };
3510FFF91D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3510FFF71D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h */; };
@@ -117,10 +113,10 @@
3566C7671D4A77BA008152BC /* MGLShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3566C7641D4A77BA008152BC /* MGLShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
3566C7681D4A77BA008152BC /* MGLShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3566C7651D4A77BA008152BC /* MGLShapeSource.mm */; };
3566C7691D4A77BA008152BC /* MGLShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3566C7651D4A77BA008152BC /* MGLShapeSource.mm */; };
- 3566C76C1D4A8DFA008152BC /* MGLRasterSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3566C76A1D4A8DFA008152BC /* MGLRasterSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 3566C76D1D4A8DFA008152BC /* MGLRasterSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3566C76A1D4A8DFA008152BC /* MGLRasterSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 3566C76E1D4A8DFA008152BC /* MGLRasterSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3566C76B1D4A8DFA008152BC /* MGLRasterSource.mm */; };
- 3566C76F1D4A8DFA008152BC /* MGLRasterSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3566C76B1D4A8DFA008152BC /* MGLRasterSource.mm */; };
+ 3566C76C1D4A8DFA008152BC /* MGLRasterTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3566C76A1D4A8DFA008152BC /* MGLRasterTileSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 3566C76D1D4A8DFA008152BC /* MGLRasterTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3566C76A1D4A8DFA008152BC /* MGLRasterTileSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 3566C76E1D4A8DFA008152BC /* MGLRasterTileSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3566C76B1D4A8DFA008152BC /* MGLRasterTileSource.mm */; };
+ 3566C76F1D4A8DFA008152BC /* MGLRasterTileSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3566C76B1D4A8DFA008152BC /* MGLRasterTileSource.mm */; };
3566C7711D4A9198008152BC /* MGLSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 3566C7701D4A9198008152BC /* MGLSource_Private.h */; };
3566C7721D4A9198008152BC /* MGLSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 3566C7701D4A9198008152BC /* MGLSource_Private.h */; };
357579801D501E09000B822E /* MGLFillStyleLayerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3575797F1D501E09000B822E /* MGLFillStyleLayerTests.mm */; };
@@ -187,13 +183,77 @@
404C26E51D89B877000AA13D /* MGLTileSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 404C26E11D89B877000AA13D /* MGLTileSource.mm */; };
404C26E71D89C55D000AA13D /* MGLTileSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E61D89C515000AA13D /* MGLTileSource_Private.h */; };
404C26E81D89C55D000AA13D /* MGLTileSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E61D89C515000AA13D /* MGLTileSource_Private.h */; };
- 40599F0C1DEE1B7600182B5D /* api_mapbox_staging.der in Resources */ = {isa = PBXBuildFile; fileRef = 40599F001DEE1B2400182B5D /* api_mapbox_staging.der */; };
- 40599F0D1DEE1B7A00182B5D /* api_mapbox_com-digicert_2016.der in Resources */ = {isa = PBXBuildFile; fileRef = 40599F011DEE1B2400182B5D /* api_mapbox_com-digicert_2016.der */; };
- 40599F0E1DEE1B7E00182B5D /* api_mapbox_com-geotrust_2016.der in Resources */ = {isa = PBXBuildFile; fileRef = 40599F021DEE1B2400182B5D /* api_mapbox_com-geotrust_2016.der */; };
+ 406E99B91FFEFF1B00D9FFCC /* MMEEventLogReportViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 406E99B11FFEFED500D9FFCC /* MMEEventLogReportViewController.m */; };
+ 406E99BA1FFEFF1B00D9FFCC /* MMEEventLogReportViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 406E99B11FFEFED500D9FFCC /* MMEEventLogReportViewController.m */; };
+ 406E99BB1FFF006C00D9FFCC /* MMEUINavigation.m in Sources */ = {isa = PBXBuildFile; fileRef = 406E99B21FFEFED500D9FFCC /* MMEUINavigation.m */; };
+ 406E99BC1FFF006D00D9FFCC /* MMEUINavigation.m in Sources */ = {isa = PBXBuildFile; fileRef = 406E99B21FFEFED500D9FFCC /* MMEUINavigation.m */; };
+ 40834BE61FE05E1800C1BD0D /* CLLocation+MMEMobileEvents.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BC31FE05D6F00C1BD0D /* CLLocation+MMEMobileEvents.m */; };
+ 40834BE71FE05E1800C1BD0D /* MMEAPIClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BA51FE05D6B00C1BD0D /* MMEAPIClient.m */; };
+ 40834BE81FE05E1800C1BD0D /* MMECategoryLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BC41FE05D6F00C1BD0D /* MMECategoryLoader.m */; };
+ 40834BE91FE05E1800C1BD0D /* MMECommonEventData.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BCE1FE05D7100C1BD0D /* MMECommonEventData.m */; };
+ 40834BEA1FE05E1800C1BD0D /* MMEConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BC01FE05D6E00C1BD0D /* MMEConstants.m */; };
+ 40834BEB1FE05E1800C1BD0D /* MMEDependencyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB41FE05D6D00C1BD0D /* MMEDependencyManager.m */; };
+ 40834BEC1FE05E1800C1BD0D /* MMEEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BC71FE05D7000C1BD0D /* MMEEvent.m */; };
+ 40834BED1FE05E1800C1BD0D /* MMEEventLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB71FE05D6D00C1BD0D /* MMEEventLogger.m */; };
+ 40834BEE1FE05E1800C1BD0D /* MMEEventsConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB21FE05D6D00C1BD0D /* MMEEventsConfiguration.m */; };
+ 40834BEF1FE05E1800C1BD0D /* MMEEventsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BA41FE05D6B00C1BD0D /* MMEEventsManager.m */; };
+ 40834BF01FE05E1800C1BD0D /* MMELocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB81FE05D6D00C1BD0D /* MMELocationManager.m */; };
+ 40834BF11FE05E1800C1BD0D /* MMENSDateWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BBC1FE05D6E00C1BD0D /* MMENSDateWrapper.m */; };
+ 40834BF21FE05E1800C1BD0D /* MMENSURLSessionWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BC61FE05D7000C1BD0D /* MMENSURLSessionWrapper.m */; };
+ 40834BF31FE05E1800C1BD0D /* MMETimerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB91FE05D6E00C1BD0D /* MMETimerManager.m */; };
+ 40834BF41FE05E1800C1BD0D /* MMETrustKitWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BC11FE05D6F00C1BD0D /* MMETrustKitWrapper.m */; };
+ 40834BF51FE05E1800C1BD0D /* MMETypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BBD1FE05D6E00C1BD0D /* MMETypes.m */; };
+ 40834BF61FE05E1800C1BD0D /* MMEUIApplicationWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BCA1FE05D7000C1BD0D /* MMEUIApplicationWrapper.m */; };
+ 40834BF71FE05E1800C1BD0D /* MMEUniqueIdentifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BAD1FE05D6C00C1BD0D /* MMEUniqueIdentifier.m */; };
+ 40834BF81FE05E1800C1BD0D /* NSData+MMEGZIP.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BAF1FE05D6C00C1BD0D /* NSData+MMEGZIP.m */; };
+ 40834BF91FE05E1800C1BD0D /* MMEReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BCD1FE05D7100C1BD0D /* MMEReachability.m */; };
+ 40834BFA1FE05E1800C1BD0D /* CLLocation+MMEMobileEvents.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BC31FE05D6F00C1BD0D /* CLLocation+MMEMobileEvents.m */; };
+ 40834BFB1FE05E1800C1BD0D /* MMEAPIClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BA51FE05D6B00C1BD0D /* MMEAPIClient.m */; };
+ 40834BFC1FE05E1800C1BD0D /* MMECategoryLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BC41FE05D6F00C1BD0D /* MMECategoryLoader.m */; };
+ 40834BFD1FE05E1800C1BD0D /* MMECommonEventData.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BCE1FE05D7100C1BD0D /* MMECommonEventData.m */; };
+ 40834BFE1FE05E1800C1BD0D /* MMEConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BC01FE05D6E00C1BD0D /* MMEConstants.m */; };
+ 40834BFF1FE05E1800C1BD0D /* MMEDependencyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB41FE05D6D00C1BD0D /* MMEDependencyManager.m */; };
+ 40834C001FE05E1800C1BD0D /* MMEEvent.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BC71FE05D7000C1BD0D /* MMEEvent.m */; };
+ 40834C011FE05E1800C1BD0D /* MMEEventLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB71FE05D6D00C1BD0D /* MMEEventLogger.m */; };
+ 40834C021FE05E1800C1BD0D /* MMEEventsConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB21FE05D6D00C1BD0D /* MMEEventsConfiguration.m */; };
+ 40834C031FE05E1800C1BD0D /* MMEEventsManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BA41FE05D6B00C1BD0D /* MMEEventsManager.m */; };
+ 40834C041FE05E1800C1BD0D /* MMELocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB81FE05D6D00C1BD0D /* MMELocationManager.m */; };
+ 40834C051FE05E1800C1BD0D /* MMENSDateWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BBC1FE05D6E00C1BD0D /* MMENSDateWrapper.m */; };
+ 40834C061FE05E1800C1BD0D /* MMENSURLSessionWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BC61FE05D7000C1BD0D /* MMENSURLSessionWrapper.m */; };
+ 40834C071FE05E1800C1BD0D /* MMETimerManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BB91FE05D6E00C1BD0D /* MMETimerManager.m */; };
+ 40834C081FE05E1800C1BD0D /* MMETrustKitWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BC11FE05D6F00C1BD0D /* MMETrustKitWrapper.m */; };
+ 40834C091FE05E1800C1BD0D /* MMETypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BBD1FE05D6E00C1BD0D /* MMETypes.m */; };
+ 40834C0A1FE05E1800C1BD0D /* MMEUIApplicationWrapper.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BCA1FE05D7000C1BD0D /* MMEUIApplicationWrapper.m */; };
+ 40834C0B1FE05E1800C1BD0D /* MMEUniqueIdentifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BAD1FE05D6C00C1BD0D /* MMEUniqueIdentifier.m */; };
+ 40834C0C1FE05E1800C1BD0D /* NSData+MMEGZIP.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BAF1FE05D6C00C1BD0D /* NSData+MMEGZIP.m */; };
+ 40834C0D1FE05E1800C1BD0D /* MMEReachability.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834BCD1FE05D7100C1BD0D /* MMEReachability.m */; };
+ 40834C401FE05F7500C1BD0D /* configuration_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C101FE05F3600C1BD0D /* configuration_utils.m */; };
+ 40834C411FE05F7500C1BD0D /* parse_configuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C141FE05F3600C1BD0D /* parse_configuration.m */; };
+ 40834C421FE05F7500C1BD0D /* ssl_pin_verifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C171FE05F3600C1BD0D /* ssl_pin_verifier.m */; };
+ 40834C431FE05F7500C1BD0D /* TSKSPKIHashCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C1A1FE05F3600C1BD0D /* TSKSPKIHashCache.m */; };
+ 40834C441FE05F7500C1BD0D /* reporting_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C1D1FE05F3600C1BD0D /* reporting_utils.m */; };
+ 40834C451FE05F7500C1BD0D /* TSKBackgroundReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C1F1FE05F3600C1BD0D /* TSKBackgroundReporter.m */; };
+ 40834C461FE05F7500C1BD0D /* TSKPinFailureReport.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C211FE05F3600C1BD0D /* TSKPinFailureReport.m */; };
+ 40834C471FE05F7500C1BD0D /* TSKReportsRateLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C231FE05F3600C1BD0D /* TSKReportsRateLimiter.m */; };
+ 40834C481FE05F7500C1BD0D /* vendor_identifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C251FE05F3600C1BD0D /* vendor_identifier.m */; };
+ 40834C491FE05F7500C1BD0D /* TrustKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C271FE05F3600C1BD0D /* TrustKit.m */; };
+ 40834C4A1FE05F7500C1BD0D /* TSKPinningValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C2A1FE05F3600C1BD0D /* TSKPinningValidator.m */; };
+ 40834C4B1FE05F7500C1BD0D /* TSKPinningValidatorResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C2E1FE05F3600C1BD0D /* TSKPinningValidatorResult.m */; };
+ 40834C4C1FE05F7500C1BD0D /* TSKTrustKitConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C311FE05F3600C1BD0D /* TSKTrustKitConfig.m */; };
+ 40834C4D1FE05F7600C1BD0D /* configuration_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C101FE05F3600C1BD0D /* configuration_utils.m */; };
+ 40834C4E1FE05F7600C1BD0D /* parse_configuration.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C141FE05F3600C1BD0D /* parse_configuration.m */; };
+ 40834C4F1FE05F7600C1BD0D /* ssl_pin_verifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C171FE05F3600C1BD0D /* ssl_pin_verifier.m */; };
+ 40834C501FE05F7600C1BD0D /* TSKSPKIHashCache.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C1A1FE05F3600C1BD0D /* TSKSPKIHashCache.m */; };
+ 40834C511FE05F7600C1BD0D /* reporting_utils.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C1D1FE05F3600C1BD0D /* reporting_utils.m */; };
+ 40834C521FE05F7600C1BD0D /* TSKBackgroundReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C1F1FE05F3600C1BD0D /* TSKBackgroundReporter.m */; };
+ 40834C531FE05F7600C1BD0D /* TSKPinFailureReport.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C211FE05F3600C1BD0D /* TSKPinFailureReport.m */; };
+ 40834C541FE05F7600C1BD0D /* TSKReportsRateLimiter.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C231FE05F3600C1BD0D /* TSKReportsRateLimiter.m */; };
+ 40834C551FE05F7600C1BD0D /* vendor_identifier.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C251FE05F3600C1BD0D /* vendor_identifier.m */; };
+ 40834C561FE05F7600C1BD0D /* TrustKit.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C271FE05F3600C1BD0D /* TrustKit.m */; };
+ 40834C571FE05F7600C1BD0D /* TSKPinningValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C2A1FE05F3600C1BD0D /* TSKPinningValidator.m */; };
+ 40834C581FE05F7600C1BD0D /* TSKPinningValidatorResult.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C2E1FE05F3600C1BD0D /* TSKPinningValidatorResult.m */; };
+ 40834C591FE05F7600C1BD0D /* TSKTrustKitConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = 40834C311FE05F3600C1BD0D /* TSKTrustKitConfig.m */; };
4085AF091D933DEA00F11B22 /* MGLTileSetTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4085AF081D933DEA00F11B22 /* MGLTileSetTests.mm */; };
- 408982E91DEE208200754016 /* api_mapbox_staging.der in Resources */ = {isa = PBXBuildFile; fileRef = 40599F001DEE1B2400182B5D /* api_mapbox_staging.der */; };
- 408982EA1DEE208B00754016 /* api_mapbox_com-digicert_2016.der in Resources */ = {isa = PBXBuildFile; fileRef = 40599F011DEE1B2400182B5D /* api_mapbox_com-digicert_2016.der */; };
- 408982EB1DEE209100754016 /* api_mapbox_com-geotrust_2016.der in Resources */ = {isa = PBXBuildFile; fileRef = 40599F021DEE1B2400182B5D /* api_mapbox_com-geotrust_2016.der */; };
408AA8571DAEDA1700022900 /* NSDictionary+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 408AA8551DAEDA0800022900 /* NSDictionary+MGLAdditions.h */; };
408AA8581DAEDA1E00022900 /* NSDictionary+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 408AA8561DAEDA0800022900 /* NSDictionary+MGLAdditions.mm */; };
408AA8591DAEDA1E00022900 /* NSDictionary+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 408AA8561DAEDA0800022900 /* NSDictionary+MGLAdditions.mm */; };
@@ -201,10 +261,6 @@
409F43FD1E9E781C0048729D /* MGLMapViewDelegateIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 409F43FC1E9E781C0048729D /* MGLMapViewDelegateIntegrationTests.swift */; };
40CF6DBB1DAC3C6600A4D18B /* MGLShape_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 40CF6DBA1DAC3C1800A4D18B /* MGLShape_Private.h */; };
40CFA6511D7875BB008103BD /* MGLShapeSourceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 40CFA6501D787579008103BD /* MGLShapeSourceTests.mm */; };
- 40EA6BC11EF4599600FCCDA2 /* api_mapbox_com-digicert_2017.der in Resources */ = {isa = PBXBuildFile; fileRef = 40EA6BBD1EF4598900FCCDA2 /* api_mapbox_com-digicert_2017.der */; };
- 40EA6BC21EF4599700FCCDA2 /* api_mapbox_com-digicert_2017.der in Resources */ = {isa = PBXBuildFile; fileRef = 40EA6BBD1EF4598900FCCDA2 /* api_mapbox_com-digicert_2017.der */; };
- 40EA6BC31EF4599D00FCCDA2 /* api_mapbox_com-geotrust_2017.der in Resources */ = {isa = PBXBuildFile; fileRef = 40EA6BBE1EF4598900FCCDA2 /* api_mapbox_com-geotrust_2017.der */; };
- 40EA6BC41EF4599D00FCCDA2 /* api_mapbox_com-geotrust_2017.der in Resources */ = {isa = PBXBuildFile; fileRef = 40EA6BBE1EF4598900FCCDA2 /* api_mapbox_com-geotrust_2017.der */; };
40EDA1C01CFE0E0200D9EA68 /* MGLAnnotationContainerView.h in Headers */ = {isa = PBXBuildFile; fileRef = 40EDA1BD1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.h */; };
40EDA1C11CFE0E0500D9EA68 /* MGLAnnotationContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EDA1BE1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.m */; };
40EDA1C21CFE0E0500D9EA68 /* MGLAnnotationContainerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 40EDA1BE1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.m */; };
@@ -253,6 +309,7 @@
9620BB3B1E69FE1700705A1D /* MGLSDKUpdateChecker.mm in Sources */ = {isa = PBXBuildFile; fileRef = 9620BB371E69FE1700705A1D /* MGLSDKUpdateChecker.mm */; };
9654C1261FFC1AB900DB6A19 /* MGLPolyline_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9654C1251FFC1AB900DB6A19 /* MGLPolyline_Private.h */; };
9654C1291FFC1CCD00DB6A19 /* MGLPolygon_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 9654C1271FFC1CC000DB6A19 /* MGLPolygon_Private.h */; };
+ 9658C155204761FC00D8A674 /* MGLMapViewScaleBarTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9658C154204761FC00D8A674 /* MGLMapViewScaleBarTests.m */; };
966FCF4C1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 966FCF4A1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.h */; };
966FCF4E1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 966FCF4B1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m */; };
966FCF4F1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 966FCF4B1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m */; };
@@ -269,7 +326,7 @@
96E516E12000551100A02306 /* MGLMultiPoint_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848041CBAFA6200AB86E3 /* MGLMultiPoint_Private.h */; };
96E516E22000551900A02306 /* MGLPointCollection_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4049C2AB1DB6E05500B3F799 /* MGLPointCollection_Private.h */; };
96E516E32000552A00A02306 /* MGLAccountManager_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8847FF1CBAFA6200AB86E3 /* MGLAccountManager_Private.h */; };
- 96E516E42000560B00A02306 /* MGLAbstractShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D9474E1F67487E00E37934 /* MGLAbstractShapeSource_Private.h */; };
+ 96E516E42000560B00A02306 /* MGLComputedShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D9474E1F67487E00E37934 /* MGLComputedShapeSource_Private.h */; };
96E516E52000560B00A02306 /* MGLOfflinePack_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848061CBAFA6200AB86E3 /* MGLOfflinePack_Private.h */; };
96E516E62000560B00A02306 /* MGLOfflineRegion_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848081CBAFA6200AB86E3 /* MGLOfflineRegion_Private.h */; };
96E516E72000560B00A02306 /* MGLOfflineStorage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848091CBAFA6200AB86E3 /* MGLOfflineStorage_Private.h */; };
@@ -279,7 +336,6 @@
96E516EB2000560B00A02306 /* MGLUserLocation_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA88484B1CBAFB9800AB86E3 /* MGLUserLocation_Private.h */; };
96E516EC2000560B00A02306 /* MGLUserLocationAnnotationView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 359F57451D2FDBD5005217F1 /* MGLUserLocationAnnotationView_Private.h */; };
96E516ED200058A200A02306 /* MGLComputedShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 0778DD401F67555F00A73B34 /* MGLComputedShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 96E516EE2000590900A02306 /* MGLAbstractShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D9474F1F67487E00E37934 /* MGLAbstractShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
96E516EF2000594F00A02306 /* NSArray+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 400532FF1DB0862B0069F638 /* NSArray+MGLAdditions.h */; };
96E516F02000595800A02306 /* NSBundle+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848121CBAFA6200AB86E3 /* NSBundle+MGLAdditions.h */; };
96E516F12000596800A02306 /* NSString+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848171CBAFA6200AB86E3 /* NSString+MGLAdditions.h */; };
@@ -294,8 +350,6 @@
96E516FA20005A3D00A02306 /* MGLUserLocationHeadingArrowLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 966FCF501F3C321000F2B6DE /* MGLUserLocationHeadingArrowLayer.h */; };
96E516FB20005A4000A02306 /* MGLUserLocationHeadingBeamLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 966FCF4A1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.h */; };
96E516FC20005A4400A02306 /* MGLUserLocationHeadingIndicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */; };
- 96E516FD20005A4700A02306 /* MGLAPIClient.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848421CBAFB9800AB86E3 /* MGLAPIClient.h */; };
- 96E516FE20005A4C00A02306 /* MGLLocationManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848461CBAFB9800AB86E3 /* MGLLocationManager.h */; };
96E516FF20005A4F00A02306 /* MGLMapboxEvents.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848481CBAFB9800AB86E3 /* MGLMapboxEvents.h */; };
96E5170020005A6100A02306 /* Fabric.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848831CBB033F00AB86E3 /* Fabric.h */; };
96E5170120005A6400A02306 /* Fabric+FABKits.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848821CBB033F00AB86E3 /* Fabric+FABKits.h */; };
@@ -307,8 +361,12 @@
AC518E00201BB55A00EBC820 /* MGLTelemetryConfig.h in Headers */ = {isa = PBXBuildFile; fileRef = AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */; };
AC518E03201BB56000EBC820 /* MGLTelemetryConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */; };
AC518E04201BB56100EBC820 /* MGLTelemetryConfig.m in Sources */ = {isa = PBXBuildFile; fileRef = AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */; };
+ CA0C27942076CA19001CE5B7 /* MGLMapViewIntegrationTest.m in Sources */ = {isa = PBXBuildFile; fileRef = CA0C27932076CA19001CE5B7 /* MGLMapViewIntegrationTest.m */; };
CA55CD41202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */ = {isa = PBXBuildFile; fileRef = CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */; settings = {ATTRIBUTES = (Public, ); }; };
CA55CD42202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */ = {isa = PBXBuildFile; fileRef = CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ CAA69DA4206DCD0E007279CD /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA4A26961CB6E795000B7809 /* Mapbox.framework */; };
+ CAA69DA5206DCD0E007279CD /* Mapbox.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DA4A26961CB6E795000B7809 /* Mapbox.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
+ CABE5DAD2072FAB40003AF3C /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA8847D21CBAF91600AB86E3 /* Mapbox.framework */; };
DA00FC8E1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA00FC8F1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA00FC901D5EEB0D009AABC8 /* MGLAttributionInfo.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */; };
@@ -425,12 +483,8 @@
DA88483F1CBAFB8500AB86E3 /* MGLUserLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848391CBAFB8500AB86E3 /* MGLUserLocation.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA88484F1CBAFB9800AB86E3 /* MGLAnnotationImage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848401CBAFB9800AB86E3 /* MGLAnnotationImage_Private.h */; };
DA8848501CBAFB9800AB86E3 /* MGLAnnotationImage.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8848411CBAFB9800AB86E3 /* MGLAnnotationImage.m */; };
- DA8848511CBAFB9800AB86E3 /* MGLAPIClient.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848421CBAFB9800AB86E3 /* MGLAPIClient.h */; };
- DA8848521CBAFB9800AB86E3 /* MGLAPIClient.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8848431CBAFB9800AB86E3 /* MGLAPIClient.m */; };
DA8848531CBAFB9800AB86E3 /* MGLCompactCalloutView.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848441CBAFB9800AB86E3 /* MGLCompactCalloutView.h */; };
DA8848541CBAFB9800AB86E3 /* MGLCompactCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8848451CBAFB9800AB86E3 /* MGLCompactCalloutView.m */; };
- DA8848551CBAFB9800AB86E3 /* MGLLocationManager.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848461CBAFB9800AB86E3 /* MGLLocationManager.h */; };
- DA8848561CBAFB9800AB86E3 /* MGLLocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8848471CBAFB9800AB86E3 /* MGLLocationManager.m */; };
DA8848571CBAFB9800AB86E3 /* MGLMapboxEvents.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848481CBAFB9800AB86E3 /* MGLMapboxEvents.h */; };
DA8848581CBAFB9800AB86E3 /* MGLMapboxEvents.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8848491CBAFB9800AB86E3 /* MGLMapboxEvents.m */; };
DA8848591CBAFB9800AB86E3 /* MGLMapView.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA88484A1CBAFB9800AB86E3 /* MGLMapView.mm */; };
@@ -456,6 +510,8 @@
DA8963381CC549A100684375 /* sprites in Resources */ = {isa = PBXBuildFile; fileRef = DA8963341CC549A100684375 /* sprites */; };
DA8963391CC549A100684375 /* styles in Resources */ = {isa = PBXBuildFile; fileRef = DA8963351CC549A100684375 /* styles */; };
DA89633A1CC549A100684375 /* tiles in Resources */ = {isa = PBXBuildFile; fileRef = DA8963361CC549A100684375 /* tiles */; };
+ DA9EA82B201C0C0C00F9874D /* NSExpression+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA9EA82A201C0C0B00F9874D /* NSExpression+MGLAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ DA9EA82C201C0C0C00F9874D /* NSExpression+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA9EA82A201C0C0B00F9874D /* NSExpression+MGLAdditions.h */; };
DAA32CC31E4C6B65006F8D24 /* MGLDistanceFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 3557F7AF1E1D27D300CCA5E6 /* MGLDistanceFormatter.m */; };
DAA4E4081CBB6C9500178DFB /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA8847D21CBAF91600AB86E3 /* Mapbox.framework */; };
DAA4E4091CBB6C9500178DFB /* Mapbox.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DA8847D21CBAF91600AB86E3 /* Mapbox.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@@ -476,9 +532,7 @@
DAA4E42A1CBB730400178DFB /* NSProcessInfo+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8848161CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.m */; };
DAA4E42B1CBB730400178DFB /* NSString+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8848181CBAFA6200AB86E3 /* NSString+MGLAdditions.m */; };
DAA4E42D1CBB730400178DFB /* MGLAnnotationImage.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8848411CBAFB9800AB86E3 /* MGLAnnotationImage.m */; };
- DAA4E42E1CBB730400178DFB /* MGLAPIClient.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8848431CBAFB9800AB86E3 /* MGLAPIClient.m */; };
DAA4E42F1CBB730400178DFB /* MGLCompactCalloutView.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8848451CBAFB9800AB86E3 /* MGLCompactCalloutView.m */; };
- DAA4E4301CBB730400178DFB /* MGLLocationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8848471CBAFB9800AB86E3 /* MGLLocationManager.m */; };
DAA4E4311CBB730400178DFB /* MGLMapboxEvents.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8848491CBAFB9800AB86E3 /* MGLMapboxEvents.m */; };
DAA4E4321CBB730400178DFB /* MGLMapView.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA88484A1CBAFB9800AB86E3 /* MGLMapView.mm */; };
DAA4E4331CBB730400178DFB /* MGLUserLocation.m in Sources */ = {isa = PBXBuildFile; fileRef = DA88484C1CBAFB9800AB86E3 /* MGLUserLocation.m */; };
@@ -540,10 +594,10 @@
DAED38651D62D0FC00D7640F /* NSURL+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DAED38621D62D0FC00D7640F /* NSURL+MGLAdditions.m */; };
DAED38661D62D0FC00D7640F /* NSURL+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = DAED38621D62D0FC00D7640F /* NSURL+MGLAdditions.m */; };
DAEDC4341D603417000224FF /* MGLAttributionInfoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DAEDC4331D603417000224FF /* MGLAttributionInfoTests.m */; };
- DAF0D8101DFE0EA000B28378 /* MGLRasterSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D80F1DFE0EA000B28378 /* MGLRasterSource_Private.h */; };
- DAF0D8111DFE0EA000B28378 /* MGLRasterSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D80F1DFE0EA000B28378 /* MGLRasterSource_Private.h */; };
- DAF0D8131DFE0EC500B28378 /* MGLVectorSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D8121DFE0EC500B28378 /* MGLVectorSource_Private.h */; };
- DAF0D8141DFE0EC500B28378 /* MGLVectorSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D8121DFE0EC500B28378 /* MGLVectorSource_Private.h */; };
+ DAF0D8101DFE0EA000B28378 /* MGLRasterTileSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D80F1DFE0EA000B28378 /* MGLRasterTileSource_Private.h */; };
+ DAF0D8111DFE0EA000B28378 /* MGLRasterTileSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D80F1DFE0EA000B28378 /* MGLRasterTileSource_Private.h */; };
+ DAF0D8131DFE0EC500B28378 /* MGLVectorTileSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D8121DFE0EC500B28378 /* MGLVectorTileSource_Private.h */; };
+ DAF0D8141DFE0EC500B28378 /* MGLVectorTileSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D8121DFE0EC500B28378 /* MGLVectorTileSource_Private.h */; };
DAF0D8181DFE6B2800B28378 /* MGLAttributionInfo_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D8171DFE6B2800B28378 /* MGLAttributionInfo_Private.h */; };
DAF0D8191DFE6B2800B28378 /* MGLAttributionInfo_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAF0D8171DFE6B2800B28378 /* MGLAttributionInfo_Private.h */; };
DAF25719201901E200367EF5 /* MGLHillshadeStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = DAF25717201901E100367EF5 /* MGLHillshadeStyleLayer.mm */; };
@@ -577,6 +631,13 @@
remoteGlobalIDString = DA8847D11CBAF91600AB86E3;
remoteInfo = dynamic;
};
+ CABE5DAB2072FA660003AF3C /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = DA1DC9421CB6C1C2006E619F /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 16376B2E1FFDB4B40000563E;
+ remoteInfo = "Integration Test Harness";
+ };
DA25D5C71CCDA0C100607828 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = DA1DC9421CB6C1C2006E619F /* Project object */;
@@ -622,6 +683,17 @@
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
+ CAA69DA6206DCD0E007279CD /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ CAA69DA5206DCD0E007279CD /* Mapbox.framework in Embed Frameworks */,
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
DA4A269A1CB6F5D3000B7809 /* Embed Frameworks */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 2147483647;
@@ -662,9 +734,7 @@
0778DD401F67555F00A73B34 /* MGLComputedShapeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLComputedShapeSource.h; sourceTree = "<group>"; };
0778DD411F67555F00A73B34 /* MGLComputedShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLComputedShapeSource.mm; sourceTree = "<group>"; };
07D8C6FD1F67562800381808 /* MGLComputedShapeSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLComputedShapeSourceTests.m; path = ../../darwin/test/MGLComputedShapeSourceTests.m; sourceTree = "<group>"; };
- 07D9474E1F67487E00E37934 /* MGLAbstractShapeSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAbstractShapeSource_Private.h; sourceTree = "<group>"; };
- 07D9474F1F67487E00E37934 /* MGLAbstractShapeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAbstractShapeSource.h; sourceTree = "<group>"; };
- 07D947501F67487E00E37934 /* MGLAbstractShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAbstractShapeSource.mm; sourceTree = "<group>"; };
+ 07D9474E1F67487E00E37934 /* MGLComputedShapeSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLComputedShapeSource_Private.h; sourceTree = "<group>"; };
16376B071FFD9DAF0000563E /* integration.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = integration.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
16376B091FFD9DAF0000563E /* MBGLIntegrationTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MBGLIntegrationTests.m; sourceTree = "<group>"; };
16376B0B1FFD9DAF0000563E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -689,8 +759,8 @@
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>"; };
- 350098BA1D480108004B2AF0 /* MGLVectorSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLVectorSource.mm; sourceTree = "<group>"; };
+ 350098B91D480108004B2AF0 /* MGLVectorTileSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorTileSource.h; sourceTree = "<group>"; };
+ 350098BA1D480108004B2AF0 /* MGLVectorTileSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLVectorTileSource.mm; sourceTree = "<group>"; };
350098DA1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSValue+MGLStyleAttributeAdditions.h"; sourceTree = "<group>"; };
350098DB1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSValue+MGLStyleAttributeAdditions.mm"; sourceTree = "<group>"; };
3510FFE81D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSComparisonPredicate+MGLAdditions.h"; sourceTree = "<group>"; };
@@ -730,8 +800,8 @@
355ADFFC1E9281DA00F3939D /* MGLScaleBar.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLScaleBar.mm; sourceTree = "<group>"; };
3566C7641D4A77BA008152BC /* MGLShapeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeSource.h; sourceTree = "<group>"; };
3566C7651D4A77BA008152BC /* MGLShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLShapeSource.mm; sourceTree = "<group>"; };
- 3566C76A1D4A8DFA008152BC /* MGLRasterSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLRasterSource.h; sourceTree = "<group>"; };
- 3566C76B1D4A8DFA008152BC /* MGLRasterSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLRasterSource.mm; sourceTree = "<group>"; };
+ 3566C76A1D4A8DFA008152BC /* MGLRasterTileSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLRasterTileSource.h; sourceTree = "<group>"; };
+ 3566C76B1D4A8DFA008152BC /* MGLRasterTileSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLRasterTileSource.mm; sourceTree = "<group>"; };
3566C7701D4A9198008152BC /* MGLSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLSource_Private.h; sourceTree = "<group>"; };
3575797F1D501E09000B822E /* MGLFillStyleLayerTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFillStyleLayerTests.mm; path = ../../darwin/test/MGLFillStyleLayerTests.mm; sourceTree = "<group>"; };
357579821D502AE6000B822E /* MGLRasterStyleLayerTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLRasterStyleLayerTests.mm; path = ../../darwin/test/MGLRasterStyleLayerTests.mm; sourceTree = "<group>"; };
@@ -776,9 +846,84 @@
404C26E01D89B877000AA13D /* MGLTileSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSource.h; sourceTree = "<group>"; };
404C26E11D89B877000AA13D /* MGLTileSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSource.mm; sourceTree = "<group>"; };
404C26E61D89C515000AA13D /* MGLTileSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSource_Private.h; sourceTree = "<group>"; };
- 40599F001DEE1B2400182B5D /* api_mapbox_staging.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = api_mapbox_staging.der; sourceTree = "<group>"; };
- 40599F011DEE1B2400182B5D /* api_mapbox_com-digicert_2016.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = "api_mapbox_com-digicert_2016.der"; sourceTree = "<group>"; };
- 40599F021DEE1B2400182B5D /* api_mapbox_com-geotrust_2016.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = "api_mapbox_com-geotrust_2016.der"; sourceTree = "<group>"; };
+ 406E99B11FFEFED500D9FFCC /* MMEEventLogReportViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMEEventLogReportViewController.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEEventLogReportViewController.m"; sourceTree = SOURCE_ROOT; };
+ 406E99B21FFEFED500D9FFCC /* MMEUINavigation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMEUINavigation.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEUINavigation.m"; sourceTree = SOURCE_ROOT; };
+ 406E99B31FFEFED600D9FFCC /* MMEUINavigation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEUINavigation.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEUINavigation.h"; sourceTree = SOURCE_ROOT; };
+ 406E99B51FFEFED600D9FFCC /* MMEEventLogReportViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEEventLogReportViewController.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEEventLogReportViewController.h"; sourceTree = SOURCE_ROOT; };
+ 40834AEF1FDF4F0100C1BD0D /* Mapbox-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "Mapbox-Prefix.pch"; path = "src/Mapbox-Prefix.pch"; sourceTree = SOURCE_ROOT; };
+ 40834BA31FE05D6B00C1BD0D /* MMEEventsManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEEventsManager.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEEventsManager.h"; sourceTree = SOURCE_ROOT; };
+ 40834BA41FE05D6B00C1BD0D /* MMEEventsManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMEEventsManager.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEEventsManager.m"; sourceTree = SOURCE_ROOT; };
+ 40834BA51FE05D6B00C1BD0D /* MMEAPIClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMEAPIClient.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEAPIClient.m"; sourceTree = SOURCE_ROOT; };
+ 40834BA61FE05D6B00C1BD0D /* MMEEventLogger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEEventLogger.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEEventLogger.h"; sourceTree = SOURCE_ROOT; };
+ 40834BA71FE05D6B00C1BD0D /* MMETrustKitWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMETrustKitWrapper.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMETrustKitWrapper.h"; sourceTree = SOURCE_ROOT; };
+ 40834BAA1FE05D6C00C1BD0D /* MMENSURLSessionWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMENSURLSessionWrapper.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMENSURLSessionWrapper.h"; sourceTree = SOURCE_ROOT; };
+ 40834BAB1FE05D6C00C1BD0D /* MMEAPIClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEAPIClient.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEAPIClient.h"; sourceTree = SOURCE_ROOT; };
+ 40834BAC1FE05D6C00C1BD0D /* MapboxMobileEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MapboxMobileEvents.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MapboxMobileEvents.h"; sourceTree = SOURCE_ROOT; };
+ 40834BAD1FE05D6C00C1BD0D /* MMEUniqueIdentifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMEUniqueIdentifier.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEUniqueIdentifier.m"; sourceTree = SOURCE_ROOT; };
+ 40834BAE1FE05D6C00C1BD0D /* MMECommonEventData.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMECommonEventData.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMECommonEventData.h"; sourceTree = SOURCE_ROOT; };
+ 40834BAF1FE05D6C00C1BD0D /* NSData+MMEGZIP.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "NSData+MMEGZIP.m"; path = "vendor/mapbox-events-ios/MapboxMobileEvents/NSData+MMEGZIP.m"; sourceTree = SOURCE_ROOT; };
+ 40834BB01FE05D6C00C1BD0D /* MMEConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEConstants.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEConstants.h"; sourceTree = SOURCE_ROOT; };
+ 40834BB11FE05D6D00C1BD0D /* MMEDependencyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEDependencyManager.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEDependencyManager.h"; sourceTree = SOURCE_ROOT; };
+ 40834BB21FE05D6D00C1BD0D /* MMEEventsConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMEEventsConfiguration.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEEventsConfiguration.m"; sourceTree = SOURCE_ROOT; };
+ 40834BB31FE05D6D00C1BD0D /* MMELocationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMELocationManager.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMELocationManager.h"; sourceTree = SOURCE_ROOT; };
+ 40834BB41FE05D6D00C1BD0D /* MMEDependencyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMEDependencyManager.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEDependencyManager.m"; sourceTree = SOURCE_ROOT; };
+ 40834BB51FE05D6D00C1BD0D /* MMECategoryLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMECategoryLoader.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMECategoryLoader.h"; sourceTree = SOURCE_ROOT; };
+ 40834BB61FE05D6D00C1BD0D /* MMETypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMETypes.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMETypes.h"; sourceTree = SOURCE_ROOT; };
+ 40834BB71FE05D6D00C1BD0D /* MMEEventLogger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMEEventLogger.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEEventLogger.m"; sourceTree = SOURCE_ROOT; };
+ 40834BB81FE05D6D00C1BD0D /* MMELocationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMELocationManager.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMELocationManager.m"; sourceTree = SOURCE_ROOT; };
+ 40834BB91FE05D6E00C1BD0D /* MMETimerManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMETimerManager.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMETimerManager.m"; sourceTree = SOURCE_ROOT; };
+ 40834BBA1FE05D6E00C1BD0D /* MMEEvent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEEvent.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEEvent.h"; sourceTree = SOURCE_ROOT; };
+ 40834BBB1FE05D6E00C1BD0D /* MMEEventsConfiguration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEEventsConfiguration.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEEventsConfiguration.h"; sourceTree = SOURCE_ROOT; };
+ 40834BBC1FE05D6E00C1BD0D /* MMENSDateWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMENSDateWrapper.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMENSDateWrapper.m"; sourceTree = SOURCE_ROOT; };
+ 40834BBD1FE05D6E00C1BD0D /* MMETypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMETypes.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMETypes.m"; sourceTree = SOURCE_ROOT; };
+ 40834BBE1FE05D6E00C1BD0D /* MMEUIApplicationWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEUIApplicationWrapper.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEUIApplicationWrapper.h"; sourceTree = SOURCE_ROOT; };
+ 40834BBF1FE05D6E00C1BD0D /* MMEUniqueIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEUniqueIdentifier.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEUniqueIdentifier.h"; sourceTree = SOURCE_ROOT; };
+ 40834BC01FE05D6E00C1BD0D /* MMEConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMEConstants.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEConstants.m"; sourceTree = SOURCE_ROOT; };
+ 40834BC11FE05D6F00C1BD0D /* MMETrustKitWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMETrustKitWrapper.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMETrustKitWrapper.m"; sourceTree = SOURCE_ROOT; };
+ 40834BC21FE05D6F00C1BD0D /* CLLocation+MMEMobileEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "CLLocation+MMEMobileEvents.h"; path = "vendor/mapbox-events-ios/MapboxMobileEvents/CLLocation+MMEMobileEvents.h"; sourceTree = SOURCE_ROOT; };
+ 40834BC31FE05D6F00C1BD0D /* CLLocation+MMEMobileEvents.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "CLLocation+MMEMobileEvents.m"; path = "vendor/mapbox-events-ios/MapboxMobileEvents/CLLocation+MMEMobileEvents.m"; sourceTree = SOURCE_ROOT; };
+ 40834BC41FE05D6F00C1BD0D /* MMECategoryLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMECategoryLoader.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMECategoryLoader.m"; sourceTree = SOURCE_ROOT; };
+ 40834BC51FE05D6F00C1BD0D /* MMENSDateWrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMENSDateWrapper.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMENSDateWrapper.h"; sourceTree = SOURCE_ROOT; };
+ 40834BC61FE05D7000C1BD0D /* MMENSURLSessionWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMENSURLSessionWrapper.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMENSURLSessionWrapper.m"; sourceTree = SOURCE_ROOT; };
+ 40834BC71FE05D7000C1BD0D /* MMEEvent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMEEvent.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEEvent.m"; sourceTree = SOURCE_ROOT; };
+ 40834BC81FE05D7000C1BD0D /* MMENamespacedDependencies.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMENamespacedDependencies.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMENamespacedDependencies.h"; sourceTree = SOURCE_ROOT; };
+ 40834BC91FE05D7000C1BD0D /* MMETimerManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMETimerManager.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMETimerManager.h"; sourceTree = SOURCE_ROOT; };
+ 40834BCA1FE05D7000C1BD0D /* MMEUIApplicationWrapper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMEUIApplicationWrapper.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMEUIApplicationWrapper.m"; sourceTree = SOURCE_ROOT; };
+ 40834BCC1FE05D7100C1BD0D /* MMEReachability.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MMEReachability.h; path = "vendor/mapbox-events-ios/MapboxMobileEvents/Reachability/MMEReachability.h"; sourceTree = SOURCE_ROOT; };
+ 40834BCD1FE05D7100C1BD0D /* MMEReachability.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMEReachability.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/Reachability/MMEReachability.m"; sourceTree = SOURCE_ROOT; };
+ 40834BCE1FE05D7100C1BD0D /* MMECommonEventData.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MMECommonEventData.m; path = "vendor/mapbox-events-ios/MapboxMobileEvents/MMECommonEventData.m"; sourceTree = SOURCE_ROOT; };
+ 40834BCF1FE05D7100C1BD0D /* NSData+MMEGZIP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "NSData+MMEGZIP.h"; path = "vendor/mapbox-events-ios/MapboxMobileEvents/NSData+MMEGZIP.h"; sourceTree = SOURCE_ROOT; };
+ 40834C0F1FE05F3600C1BD0D /* configuration_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = configuration_utils.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/configuration_utils.h"; sourceTree = SOURCE_ROOT; };
+ 40834C101FE05F3600C1BD0D /* configuration_utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = configuration_utils.m; path = "vendor/mapbox-events-ios/vendor/TrustKit/configuration_utils.m"; sourceTree = SOURCE_ROOT; };
+ 40834C131FE05F3600C1BD0D /* parse_configuration.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = parse_configuration.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/parse_configuration.h"; sourceTree = SOURCE_ROOT; };
+ 40834C141FE05F3600C1BD0D /* parse_configuration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = parse_configuration.m; path = "vendor/mapbox-events-ios/vendor/TrustKit/parse_configuration.m"; sourceTree = SOURCE_ROOT; };
+ 40834C161FE05F3600C1BD0D /* ssl_pin_verifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ssl_pin_verifier.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/Pinning/ssl_pin_verifier.h"; sourceTree = SOURCE_ROOT; };
+ 40834C171FE05F3600C1BD0D /* ssl_pin_verifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ssl_pin_verifier.m; path = "vendor/mapbox-events-ios/vendor/TrustKit/Pinning/ssl_pin_verifier.m"; sourceTree = SOURCE_ROOT; };
+ 40834C181FE05F3600C1BD0D /* TSKPublicKeyAlgorithm.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSKPublicKeyAlgorithm.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/Pinning/TSKPublicKeyAlgorithm.h"; sourceTree = SOURCE_ROOT; };
+ 40834C191FE05F3600C1BD0D /* TSKSPKIHashCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSKSPKIHashCache.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/Pinning/TSKSPKIHashCache.h"; sourceTree = SOURCE_ROOT; };
+ 40834C1A1FE05F3600C1BD0D /* TSKSPKIHashCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSKSPKIHashCache.m; path = "vendor/mapbox-events-ios/vendor/TrustKit/Pinning/TSKSPKIHashCache.m"; sourceTree = SOURCE_ROOT; };
+ 40834C1C1FE05F3600C1BD0D /* reporting_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = reporting_utils.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/Reporting/reporting_utils.h"; sourceTree = SOURCE_ROOT; };
+ 40834C1D1FE05F3600C1BD0D /* reporting_utils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = reporting_utils.m; path = "vendor/mapbox-events-ios/vendor/TrustKit/Reporting/reporting_utils.m"; sourceTree = SOURCE_ROOT; };
+ 40834C1E1FE05F3600C1BD0D /* TSKBackgroundReporter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSKBackgroundReporter.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/Reporting/TSKBackgroundReporter.h"; sourceTree = SOURCE_ROOT; };
+ 40834C1F1FE05F3600C1BD0D /* TSKBackgroundReporter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSKBackgroundReporter.m; path = "vendor/mapbox-events-ios/vendor/TrustKit/Reporting/TSKBackgroundReporter.m"; sourceTree = SOURCE_ROOT; };
+ 40834C201FE05F3600C1BD0D /* TSKPinFailureReport.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSKPinFailureReport.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/Reporting/TSKPinFailureReport.h"; sourceTree = SOURCE_ROOT; };
+ 40834C211FE05F3600C1BD0D /* TSKPinFailureReport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSKPinFailureReport.m; path = "vendor/mapbox-events-ios/vendor/TrustKit/Reporting/TSKPinFailureReport.m"; sourceTree = SOURCE_ROOT; };
+ 40834C221FE05F3600C1BD0D /* TSKReportsRateLimiter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSKReportsRateLimiter.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/Reporting/TSKReportsRateLimiter.h"; sourceTree = SOURCE_ROOT; };
+ 40834C231FE05F3600C1BD0D /* TSKReportsRateLimiter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSKReportsRateLimiter.m; path = "vendor/mapbox-events-ios/vendor/TrustKit/Reporting/TSKReportsRateLimiter.m"; sourceTree = SOURCE_ROOT; };
+ 40834C241FE05F3600C1BD0D /* vendor_identifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vendor_identifier.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/Reporting/vendor_identifier.h"; sourceTree = SOURCE_ROOT; };
+ 40834C251FE05F3600C1BD0D /* vendor_identifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = vendor_identifier.m; path = "vendor/mapbox-events-ios/vendor/TrustKit/Reporting/vendor_identifier.m"; sourceTree = SOURCE_ROOT; };
+ 40834C261FE05F3600C1BD0D /* TrustKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TrustKit.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/TrustKit.h"; sourceTree = SOURCE_ROOT; };
+ 40834C271FE05F3600C1BD0D /* TrustKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TrustKit.m; path = "vendor/mapbox-events-ios/vendor/TrustKit/TrustKit.m"; sourceTree = SOURCE_ROOT; };
+ 40834C281FE05F3600C1BD0D /* TSKLog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSKLog.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/TSKLog.h"; sourceTree = SOURCE_ROOT; };
+ 40834C291FE05F3600C1BD0D /* TSKPinningValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSKPinningValidator.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/TSKPinningValidator.h"; sourceTree = SOURCE_ROOT; };
+ 40834C2A1FE05F3600C1BD0D /* TSKPinningValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSKPinningValidator.m; path = "vendor/mapbox-events-ios/vendor/TrustKit/TSKPinningValidator.m"; sourceTree = SOURCE_ROOT; };
+ 40834C2B1FE05F3600C1BD0D /* TSKPinningValidator_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSKPinningValidator_Private.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/TSKPinningValidator_Private.h"; sourceTree = SOURCE_ROOT; };
+ 40834C2C1FE05F3600C1BD0D /* TSKPinningValidatorCallback.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSKPinningValidatorCallback.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/TSKPinningValidatorCallback.h"; sourceTree = SOURCE_ROOT; };
+ 40834C2D1FE05F3600C1BD0D /* TSKPinningValidatorResult.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSKPinningValidatorResult.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/TSKPinningValidatorResult.h"; sourceTree = SOURCE_ROOT; };
+ 40834C2E1FE05F3600C1BD0D /* TSKPinningValidatorResult.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSKPinningValidatorResult.m; path = "vendor/mapbox-events-ios/vendor/TrustKit/TSKPinningValidatorResult.m"; sourceTree = SOURCE_ROOT; };
+ 40834C2F1FE05F3600C1BD0D /* TSKTrustDecision.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSKTrustDecision.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/TSKTrustDecision.h"; sourceTree = SOURCE_ROOT; };
+ 40834C301FE05F3600C1BD0D /* TSKTrustKitConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TSKTrustKitConfig.h; path = "vendor/mapbox-events-ios/vendor/TrustKit/TSKTrustKitConfig.h"; sourceTree = SOURCE_ROOT; };
+ 40834C311FE05F3600C1BD0D /* TSKTrustKitConfig.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TSKTrustKitConfig.m; path = "vendor/mapbox-events-ios/vendor/TrustKit/TSKTrustKitConfig.m"; sourceTree = SOURCE_ROOT; };
4085AF081D933DEA00F11B22 /* MGLTileSetTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLTileSetTests.mm; path = ../../darwin/test/MGLTileSetTests.mm; sourceTree = "<group>"; };
408AA8551DAEDA0800022900 /* NSDictionary+MGLAdditions.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSDictionary+MGLAdditions.h"; sourceTree = "<group>"; };
408AA8561DAEDA0800022900 /* NSDictionary+MGLAdditions.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSDictionary+MGLAdditions.mm"; sourceTree = "<group>"; };
@@ -786,8 +931,6 @@
409F43FC1E9E781C0048729D /* MGLMapViewDelegateIntegrationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MGLMapViewDelegateIntegrationTests.swift; sourceTree = "<group>"; };
40CF6DBA1DAC3C1800A4D18B /* MGLShape_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShape_Private.h; sourceTree = "<group>"; };
40CFA6501D787579008103BD /* MGLShapeSourceTests.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLShapeSourceTests.mm; path = ../../darwin/test/MGLShapeSourceTests.mm; sourceTree = "<group>"; };
- 40EA6BBD1EF4598900FCCDA2 /* api_mapbox_com-digicert_2017.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = "api_mapbox_com-digicert_2017.der"; sourceTree = "<group>"; };
- 40EA6BBE1EF4598900FCCDA2 /* api_mapbox_com-geotrust_2017.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = "api_mapbox_com-geotrust_2017.der"; sourceTree = "<group>"; };
40EDA1BD1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationContainerView.h; sourceTree = "<group>"; };
40EDA1BE1CFE0D4A00D9EA68 /* MGLAnnotationContainerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLAnnotationContainerView.m; sourceTree = "<group>"; };
40F8876F1D7A1DB8008ECB67 /* MGLShapeSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeSource_Private.h; sourceTree = "<group>"; };
@@ -825,6 +968,7 @@
9620BB371E69FE1700705A1D /* MGLSDKUpdateChecker.mm */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.objcpp; fileEncoding = 4; path = MGLSDKUpdateChecker.mm; sourceTree = "<group>"; };
9654C1251FFC1AB900DB6A19 /* MGLPolyline_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLPolyline_Private.h; sourceTree = "<group>"; };
9654C1271FFC1CC000DB6A19 /* MGLPolygon_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLPolygon_Private.h; sourceTree = "<group>"; };
+ 9658C154204761FC00D8A674 /* MGLMapViewScaleBarTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLMapViewScaleBarTests.m; sourceTree = "<group>"; };
9660916B1E5BBFD700A9A03B /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = "<group>"; };
9660916C1E5BBFD900A9A03B /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
9660916D1E5BBFDB00A9A03B /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -847,6 +991,8 @@
96F3F73B1F5711F1003E2D2C /* MGLUserLocationHeadingIndicator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLUserLocationHeadingIndicator.h; sourceTree = "<group>"; };
AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLTelemetryConfig.h; sourceTree = "<group>"; };
AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLTelemetryConfig.m; sourceTree = "<group>"; };
+ CA0C27932076CA19001CE5B7 /* MGLMapViewIntegrationTest.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MGLMapViewIntegrationTest.m; sourceTree = "<group>"; };
+ CA0C27952076CA50001CE5B7 /* MGLMapViewIntegrationTest.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLMapViewIntegrationTest.h; sourceTree = "<group>"; };
CA55CD3E202C16AA00CE7095 /* MGLCameraChangeReason.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCameraChangeReason.h; sourceTree = "<group>"; };
DA00FC8C1D5EEB0D009AABC8 /* MGLAttributionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAttributionInfo.h; sourceTree = "<group>"; };
DA00FC8D1D5EEB0D009AABC8 /* MGLAttributionInfo.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAttributionInfo.mm; sourceTree = "<group>"; };
@@ -1002,12 +1148,8 @@
DA8848391CBAFB8500AB86E3 /* MGLUserLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLUserLocation.h; sourceTree = "<group>"; };
DA8848401CBAFB9800AB86E3 /* MGLAnnotationImage_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationImage_Private.h; sourceTree = "<group>"; };
DA8848411CBAFB9800AB86E3 /* MGLAnnotationImage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLAnnotationImage.m; sourceTree = "<group>"; };
- DA8848421CBAFB9800AB86E3 /* MGLAPIClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAPIClient.h; sourceTree = "<group>"; };
- DA8848431CBAFB9800AB86E3 /* MGLAPIClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLAPIClient.m; sourceTree = "<group>"; };
DA8848441CBAFB9800AB86E3 /* MGLCompactCalloutView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCompactCalloutView.h; sourceTree = "<group>"; };
DA8848451CBAFB9800AB86E3 /* MGLCompactCalloutView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLCompactCalloutView.m; sourceTree = "<group>"; };
- DA8848461CBAFB9800AB86E3 /* MGLLocationManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLLocationManager.h; sourceTree = "<group>"; };
- DA8848471CBAFB9800AB86E3 /* MGLLocationManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLLocationManager.m; sourceTree = "<group>"; };
DA8848481CBAFB9800AB86E3 /* MGLMapboxEvents.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLMapboxEvents.h; sourceTree = "<group>"; };
DA8848491CBAFB9800AB86E3 /* MGLMapboxEvents.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLMapboxEvents.m; sourceTree = "<group>"; };
DA88484A1CBAFB9800AB86E3 /* MGLMapView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLMapView.mm; sourceTree = "<group>"; };
@@ -1035,10 +1177,16 @@
DA8F25B91D51D2570010E6B5 /* MGLStyleLayerTests.mm.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; name = MGLStyleLayerTests.mm.ejs; path = ../test/MGLStyleLayerTests.mm.ejs; sourceTree = "<group>"; };
DA8F25BA1D51D2570010E6B5 /* MGLStyleLayer.h.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = MGLStyleLayer.h.ejs; sourceTree = "<group>"; };
DA8F25BB1D51D2570010E6B5 /* MGLStyleLayer.mm.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = MGLStyleLayer.mm.ejs; sourceTree = "<group>"; };
+ DA93409B208562EB0059919A /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = "<group>"; };
+ DA93409C2085630C0059919A /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "pt-PT"; path = "pt-PT.lproj/Foundation.stringsdict"; sourceTree = "<group>"; };
+ DA93409D208563220059919A /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = "<group>"; };
+ DA93409E208563360059919A /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "pt-PT"; path = "pt-PT.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
+ DA93409F208563440059919A /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Root.strings"; sourceTree = "<group>"; };
DA9C012B1E4C7AD900C4742A /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "pt-BR"; path = "pt-BR.lproj/Localizable.stringsdict"; sourceTree = "<group>"; };
DA9C012C1E4C7ADB00C4742A /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "pt-BR"; path = "pt-BR.lproj/Foundation.stringsdict"; sourceTree = "<group>"; };
DA9C012D1E4C7B1F00C4742A /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; };
DA9C012E1E4C7B6100C4742A /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Root.strings"; sourceTree = "<group>"; };
+ DA9EA82A201C0C0B00F9874D /* NSExpression+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSExpression+MGLAdditions.h"; sourceTree = "<group>"; };
DAA32CA11E4C44DB006F8D24 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = de; path = de.lproj/Foundation.stringsdict; sourceTree = "<group>"; };
DAA32CA21E4C44DD006F8D24 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = de; path = de.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
DAA32CA31E4C44F1006F8D24 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Foundation.strings; sourceTree = "<group>"; };
@@ -1087,6 +1235,12 @@
DAD1656B1CF41981001FF4B9 /* MGLFeature.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFeature.mm; sourceTree = "<group>"; };
DAD165761CF4CDFF001FF4B9 /* MGLShapeCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeCollection.h; sourceTree = "<group>"; };
DAD165771CF4CDFF001FF4B9 /* MGLShapeCollection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLShapeCollection.mm; sourceTree = "<group>"; };
+ DAD88E07202ACFE800AAA536 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = "<group>"; };
+ DAD88E08202AD01300AAA536 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Foundation.strings; sourceTree = "<group>"; };
+ DAD88E09202AD01F00AAA536 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = da; path = da.lproj/Foundation.stringsdict; sourceTree = "<group>"; };
+ DAD88E0A202AD03C00AAA536 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = "<group>"; };
+ DAD88E0B202AD04D00AAA536 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = da; path = da.lproj/Localizable.stringsdict; sourceTree = "<group>"; };
+ DAD88E0C202AD06500AAA536 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Root.strings; sourceTree = "<group>"; };
DAE7DEC11E245455007505A6 /* MGLNSStringAdditionsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLNSStringAdditionsTests.m; path = ../../darwin/test/MGLNSStringAdditionsTests.m; sourceTree = "<group>"; };
DAE8CCAD1E6E8C70009B5CB0 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
DAE8CCAE1E6E8C76009B5CB0 /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Root.strings; sourceTree = "<group>"; };
@@ -1094,8 +1248,8 @@
DAED38611D62D0FC00D7640F /* NSURL+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURL+MGLAdditions.h"; sourceTree = "<group>"; };
DAED38621D62D0FC00D7640F /* NSURL+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSURL+MGLAdditions.m"; sourceTree = "<group>"; };
DAEDC4331D603417000224FF /* MGLAttributionInfoTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLAttributionInfoTests.m; path = ../../darwin/test/MGLAttributionInfoTests.m; sourceTree = "<group>"; };
- DAF0D80F1DFE0EA000B28378 /* MGLRasterSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLRasterSource_Private.h; sourceTree = "<group>"; };
- DAF0D8121DFE0EC500B28378 /* MGLVectorSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorSource_Private.h; sourceTree = "<group>"; };
+ DAF0D80F1DFE0EA000B28378 /* MGLRasterTileSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLRasterTileSource_Private.h; sourceTree = "<group>"; };
+ DAF0D8121DFE0EC500B28378 /* MGLVectorTileSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorTileSource_Private.h; sourceTree = "<group>"; };
DAF0D8171DFE6B2800B28378 /* MGLAttributionInfo_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAttributionInfo_Private.h; sourceTree = "<group>"; };
DAF25717201901E100367EF5 /* MGLHillshadeStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLHillshadeStyleLayer.mm; sourceTree = "<group>"; };
DAF25718201901E200367EF5 /* MGLHillshadeStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLHillshadeStyleLayer.h; sourceTree = "<group>"; };
@@ -1121,7 +1275,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
- 165D0CE720005419009A3C66 /* Mapbox.framework in Frameworks */,
+ CABE5DAD2072FAB40003AF3C /* Mapbox.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1129,6 +1283,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ CAA69DA4206DCD0E007279CD /* Mapbox.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1188,6 +1343,8 @@
children = (
16376B091FFD9DAF0000563E /* MBGLIntegrationTests.m */,
16376B0B1FFD9DAF0000563E /* Info.plist */,
+ CA0C27932076CA19001CE5B7 /* MGLMapViewIntegrationTest.m */,
+ CA0C27952076CA50001CE5B7 /* MGLMapViewIntegrationTest.h */,
);
path = "Integration Tests";
sourceTree = "<group>";
@@ -1208,16 +1365,14 @@
35136D491D4277EA00C20EFD /* Sources */ = {
isa = PBXGroup;
children = (
- 07D9474F1F67487E00E37934 /* MGLAbstractShapeSource.h */,
- 07D9474E1F67487E00E37934 /* MGLAbstractShapeSource_Private.h */,
- 07D947501F67487E00E37934 /* MGLAbstractShapeSource.mm */,
0778DD401F67555F00A73B34 /* MGLComputedShapeSource.h */,
+ 07D9474E1F67487E00E37934 /* MGLComputedShapeSource_Private.h */,
0778DD411F67555F00A73B34 /* MGLComputedShapeSource.mm */,
071BBAFC1EE75CD4001FB02A /* MGLImageSource.h */,
071BBAFD1EE75CD4001FB02A /* MGLImageSource.mm */,
- 3566C76A1D4A8DFA008152BC /* MGLRasterSource.h */,
- DAF0D80F1DFE0EA000B28378 /* MGLRasterSource_Private.h */,
- 3566C76B1D4A8DFA008152BC /* MGLRasterSource.mm */,
+ 3566C76A1D4A8DFA008152BC /* MGLRasterTileSource.h */,
+ DAF0D80F1DFE0EA000B28378 /* MGLRasterTileSource_Private.h */,
+ 3566C76B1D4A8DFA008152BC /* MGLRasterTileSource.mm */,
DACA86242019218500E9693A /* MGLRasterDEMSource.h */,
DACA86252019218500E9693A /* MGLRasterDEMSource.mm */,
3566C7641D4A77BA008152BC /* MGLShapeSource.h */,
@@ -1229,9 +1384,9 @@
404C26E01D89B877000AA13D /* MGLTileSource.h */,
404C26E61D89C515000AA13D /* MGLTileSource_Private.h */,
404C26E11D89B877000AA13D /* MGLTileSource.mm */,
- 350098B91D480108004B2AF0 /* MGLVectorSource.h */,
- DAF0D8121DFE0EC500B28378 /* MGLVectorSource_Private.h */,
- 350098BA1D480108004B2AF0 /* MGLVectorSource.mm */,
+ 350098B91D480108004B2AF0 /* MGLVectorTileSource.h */,
+ DAF0D8121DFE0EC500B28378 /* MGLVectorTileSource_Private.h */,
+ 350098BA1D480108004B2AF0 /* MGLVectorTileSource.mm */,
);
name = Sources;
sourceTree = "<group>";
@@ -1368,6 +1523,137 @@
name = "Test Helpers";
sourceTree = "<group>";
};
+ 40834BA11FE05CFD00C1BD0D /* Development */ = {
+ isa = PBXGroup;
+ children = (
+ 9620BB361E69FE1700705A1D /* MGLSDKUpdateChecker.h */,
+ 9620BB371E69FE1700705A1D /* MGLSDKUpdateChecker.mm */,
+ );
+ name = Development;
+ sourceTree = "<group>";
+ };
+ 40834BA21FE05D3100C1BD0D /* Runtime */ = {
+ isa = PBXGroup;
+ children = (
+ 40834BC81FE05D7000C1BD0D /* MMENamespacedDependencies.h */,
+ 40834BAC1FE05D6C00C1BD0D /* MapboxMobileEvents.h */,
+ DA8848481CBAFB9800AB86E3 /* MGLMapboxEvents.h */,
+ DA8848491CBAFB9800AB86E3 /* MGLMapboxEvents.m */,
+ 40834BC21FE05D6F00C1BD0D /* CLLocation+MMEMobileEvents.h */,
+ 40834BC31FE05D6F00C1BD0D /* CLLocation+MMEMobileEvents.m */,
+ 40834BAB1FE05D6C00C1BD0D /* MMEAPIClient.h */,
+ 40834BA51FE05D6B00C1BD0D /* MMEAPIClient.m */,
+ 40834BB51FE05D6D00C1BD0D /* MMECategoryLoader.h */,
+ 40834BC41FE05D6F00C1BD0D /* MMECategoryLoader.m */,
+ 40834BAE1FE05D6C00C1BD0D /* MMECommonEventData.h */,
+ 40834BCE1FE05D7100C1BD0D /* MMECommonEventData.m */,
+ 40834BB01FE05D6C00C1BD0D /* MMEConstants.h */,
+ 40834BC01FE05D6E00C1BD0D /* MMEConstants.m */,
+ 40834BB11FE05D6D00C1BD0D /* MMEDependencyManager.h */,
+ 40834BB41FE05D6D00C1BD0D /* MMEDependencyManager.m */,
+ 40834BBA1FE05D6E00C1BD0D /* MMEEvent.h */,
+ 40834BC71FE05D7000C1BD0D /* MMEEvent.m */,
+ 40834BA61FE05D6B00C1BD0D /* MMEEventLogger.h */,
+ 40834BB71FE05D6D00C1BD0D /* MMEEventLogger.m */,
+ 406E99B51FFEFED600D9FFCC /* MMEEventLogReportViewController.h */,
+ 406E99B11FFEFED500D9FFCC /* MMEEventLogReportViewController.m */,
+ 40834BBB1FE05D6E00C1BD0D /* MMEEventsConfiguration.h */,
+ 40834BB21FE05D6D00C1BD0D /* MMEEventsConfiguration.m */,
+ 40834BA31FE05D6B00C1BD0D /* MMEEventsManager.h */,
+ 40834BA41FE05D6B00C1BD0D /* MMEEventsManager.m */,
+ 40834BB31FE05D6D00C1BD0D /* MMELocationManager.h */,
+ 40834BB81FE05D6D00C1BD0D /* MMELocationManager.m */,
+ 40834BC51FE05D6F00C1BD0D /* MMENSDateWrapper.h */,
+ 40834BBC1FE05D6E00C1BD0D /* MMENSDateWrapper.m */,
+ 40834BAA1FE05D6C00C1BD0D /* MMENSURLSessionWrapper.h */,
+ 40834BC61FE05D7000C1BD0D /* MMENSURLSessionWrapper.m */,
+ 40834BC91FE05D7000C1BD0D /* MMETimerManager.h */,
+ 40834BB91FE05D6E00C1BD0D /* MMETimerManager.m */,
+ 40834BA71FE05D6B00C1BD0D /* MMETrustKitWrapper.h */,
+ 40834BC11FE05D6F00C1BD0D /* MMETrustKitWrapper.m */,
+ 40834BB61FE05D6D00C1BD0D /* MMETypes.h */,
+ 40834BBD1FE05D6E00C1BD0D /* MMETypes.m */,
+ 40834BBE1FE05D6E00C1BD0D /* MMEUIApplicationWrapper.h */,
+ 40834BCA1FE05D7000C1BD0D /* MMEUIApplicationWrapper.m */,
+ 406E99B31FFEFED600D9FFCC /* MMEUINavigation.h */,
+ 406E99B21FFEFED500D9FFCC /* MMEUINavigation.m */,
+ 40834BBF1FE05D6E00C1BD0D /* MMEUniqueIdentifier.h */,
+ 40834BAD1FE05D6C00C1BD0D /* MMEUniqueIdentifier.m */,
+ 40834BCF1FE05D7100C1BD0D /* NSData+MMEGZIP.h */,
+ 40834BAF1FE05D6C00C1BD0D /* NSData+MMEGZIP.m */,
+ 40834BCB1FE05D7100C1BD0D /* Reachability */,
+ 40834C0E1FE05F3600C1BD0D /* TrustKit */,
+ );
+ name = Runtime;
+ sourceTree = "<group>";
+ };
+ 40834BCB1FE05D7100C1BD0D /* Reachability */ = {
+ isa = PBXGroup;
+ children = (
+ 40834BCC1FE05D7100C1BD0D /* MMEReachability.h */,
+ 40834BCD1FE05D7100C1BD0D /* MMEReachability.m */,
+ );
+ name = Reachability;
+ path = "vendor/mapbox-events-ios/MapboxMobileEvents/Reachability";
+ sourceTree = SOURCE_ROOT;
+ };
+ 40834C0E1FE05F3600C1BD0D /* TrustKit */ = {
+ isa = PBXGroup;
+ children = (
+ 40834C0F1FE05F3600C1BD0D /* configuration_utils.h */,
+ 40834C101FE05F3600C1BD0D /* configuration_utils.m */,
+ 40834C131FE05F3600C1BD0D /* parse_configuration.h */,
+ 40834C141FE05F3600C1BD0D /* parse_configuration.m */,
+ 40834C151FE05F3600C1BD0D /* Pinning */,
+ 40834C1B1FE05F3600C1BD0D /* Reporting */,
+ 40834C261FE05F3600C1BD0D /* TrustKit.h */,
+ 40834C271FE05F3600C1BD0D /* TrustKit.m */,
+ 40834C281FE05F3600C1BD0D /* TSKLog.h */,
+ 40834C291FE05F3600C1BD0D /* TSKPinningValidator.h */,
+ 40834C2A1FE05F3600C1BD0D /* TSKPinningValidator.m */,
+ 40834C2B1FE05F3600C1BD0D /* TSKPinningValidator_Private.h */,
+ 40834C2C1FE05F3600C1BD0D /* TSKPinningValidatorCallback.h */,
+ 40834C2D1FE05F3600C1BD0D /* TSKPinningValidatorResult.h */,
+ 40834C2E1FE05F3600C1BD0D /* TSKPinningValidatorResult.m */,
+ 40834C2F1FE05F3600C1BD0D /* TSKTrustDecision.h */,
+ 40834C301FE05F3600C1BD0D /* TSKTrustKitConfig.h */,
+ 40834C311FE05F3600C1BD0D /* TSKTrustKitConfig.m */,
+ );
+ name = TrustKit;
+ path = "vendor/mapbox-events-ios/vendor/TrustKit";
+ sourceTree = SOURCE_ROOT;
+ };
+ 40834C151FE05F3600C1BD0D /* Pinning */ = {
+ isa = PBXGroup;
+ children = (
+ 40834C161FE05F3600C1BD0D /* ssl_pin_verifier.h */,
+ 40834C171FE05F3600C1BD0D /* ssl_pin_verifier.m */,
+ 40834C181FE05F3600C1BD0D /* TSKPublicKeyAlgorithm.h */,
+ 40834C191FE05F3600C1BD0D /* TSKSPKIHashCache.h */,
+ 40834C1A1FE05F3600C1BD0D /* TSKSPKIHashCache.m */,
+ );
+ name = Pinning;
+ path = "vendor/mapbox-events-ios/vendor/TrustKit/Pinning";
+ sourceTree = SOURCE_ROOT;
+ };
+ 40834C1B1FE05F3600C1BD0D /* Reporting */ = {
+ isa = PBXGroup;
+ children = (
+ 40834C1C1FE05F3600C1BD0D /* reporting_utils.h */,
+ 40834C1D1FE05F3600C1BD0D /* reporting_utils.m */,
+ 40834C1E1FE05F3600C1BD0D /* TSKBackgroundReporter.h */,
+ 40834C1F1FE05F3600C1BD0D /* TSKBackgroundReporter.m */,
+ 40834C201FE05F3600C1BD0D /* TSKPinFailureReport.h */,
+ 40834C211FE05F3600C1BD0D /* TSKPinFailureReport.m */,
+ 40834C221FE05F3600C1BD0D /* TSKReportsRateLimiter.h */,
+ 40834C231FE05F3600C1BD0D /* TSKReportsRateLimiter.m */,
+ 40834C241FE05F3600C1BD0D /* vendor_identifier.h */,
+ 40834C251FE05F3600C1BD0D /* vendor_identifier.m */,
+ );
+ name = Reporting;
+ path = "vendor/mapbox-events-ios/vendor/TrustKit/Reporting";
+ sourceTree = SOURCE_ROOT;
+ };
409F43FB1E9E77D10048729D /* Swift Integration */ = {
isa = PBXGroup;
children = (
@@ -1512,24 +1798,25 @@
4031ACFD1E9FD26900A3EA26 /* Test Helpers */,
409F43FB1E9E77D10048729D /* Swift Integration */,
357579811D502AD4000B822E /* Styling */,
- DAEDC4331D603417000224FF /* MGLAttributionInfoTests.m */,
353D23951D0B0DFE002BE09D /* MGLAnnotationViewTests.m */,
+ DAEDC4331D603417000224FF /* MGLAttributionInfoTests.m */,
DA35A2C31CCA9F8300E826B2 /* MGLClockDirectionFormatterTests.m */,
35D9DDE11DA25EEC00DAAD69 /* MGLCodingTests.m */,
DA35A2C41CCA9F8300E826B2 /* MGLCompassDirectionFormatterTests.m */,
DA35A2A91CCA058D00E826B2 /* MGLCoordinateFormatterTests.m */,
+ 3598544C1E1D38AA00B29F84 /* MGLDistanceFormatterTests.m */,
6407D66F1E0085FD00F6A9C3 /* MGLDocumentationExampleTests.swift */,
DA1F8F3C1EBD287B00367E42 /* MGLDocumentationGuideTests.swift */,
DD58A4C51D822BD000E1F038 /* MGLExpressionTests.mm */,
- 3598544C1E1D38AA00B29F84 /* MGLDistanceFormatterTests.m */,
DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */,
DA2E885C1CC0382C00F24E7B /* MGLGeometryTests.mm */,
DA5DB1291FABF1EE001C2326 /* MGLMapAccessibilityElementTests.m */,
16376B481FFEED010000563E /* MGLMapViewLayoutTests.m */,
+ 9658C154204761FC00D8A674 /* MGLMapViewScaleBarTests.m */,
35E208A61D24210F00EC9A46 /* MGLNSDataAdditionsTests.m */,
1F95931C1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm */,
- DAE7DEC11E245455007505A6 /* MGLNSStringAdditionsTests.m */,
96036A0520059BBA00510F3D /* MGLNSOrthographyAdditionsTests.m */,
+ DAE7DEC11E245455007505A6 /* MGLNSStringAdditionsTests.m */,
DA2E885D1CC0382C00F24E7B /* MGLOfflinePackTests.m */,
DA2E885E1CC0382C00F24E7B /* MGLOfflineRegionTests.m */,
55E2AD121E5B125400E8C587 /* MGLOfflineStorageTests.mm */,
@@ -1548,6 +1835,7 @@
isa = PBXGroup;
children = (
DA88485E1CBAFC2E00AB86E3 /* Mapbox.h */,
+ 40834AEF1FDF4F0100C1BD0D /* Mapbox-Prefix.pch */,
DA8847DE1CBAFA3E00AB86E3 /* Foundation */,
DA8F25BC1D51D2570010E6B5 /* Foundation Templates */,
DA8933B91CCD2C6700E68420 /* Foundation Resources */,
@@ -1627,11 +1915,6 @@
DA89339F1CCC951200E68420 /* Localizable.strings */,
DAC49C5F1CD02BC9009E1AA3 /* Localizable.stringsdict */,
DA8933EF1CCD387900E68420 /* strip-frameworks.sh */,
- 40599F001DEE1B2400182B5D /* api_mapbox_staging.der */,
- 40599F011DEE1B2400182B5D /* api_mapbox_com-digicert_2016.der */,
- 40599F021DEE1B2400182B5D /* api_mapbox_com-geotrust_2016.der */,
- 40EA6BBD1EF4598900FCCDA2 /* api_mapbox_com-digicert_2017.der */,
- 40EA6BBE1EF4598900FCCDA2 /* api_mapbox_com-geotrust_2017.der */,
);
name = "Kit Resources";
path = resources;
@@ -1813,6 +2096,7 @@
408AA8561DAEDA0800022900 /* NSDictionary+MGLAdditions.mm */,
DA8848141CBAFA6200AB86E3 /* NSException+MGLAdditions.h */,
3510FFEE1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h */,
+ DA9EA82A201C0C0B00F9874D /* NSExpression+MGLAdditions.h */,
DAC25FCB200FD83E009BE98E /* NSExpression+MGLPrivateAdditions.h */,
3510FFEF1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm */,
35B82BF61D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h */,
@@ -1864,16 +2148,10 @@
DAD165851CF4D08B001FF4B9 /* Telemetry */ = {
isa = PBXGroup;
children = (
- DA8848421CBAFB9800AB86E3 /* MGLAPIClient.h */,
- DA8848431CBAFB9800AB86E3 /* MGLAPIClient.m */,
- DA8848461CBAFB9800AB86E3 /* MGLLocationManager.h */,
- DA8848471CBAFB9800AB86E3 /* MGLLocationManager.m */,
- DA8848481CBAFB9800AB86E3 /* MGLMapboxEvents.h */,
- DA8848491CBAFB9800AB86E3 /* MGLMapboxEvents.m */,
- 9620BB361E69FE1700705A1D /* MGLSDKUpdateChecker.h */,
- 9620BB371E69FE1700705A1D /* MGLSDKUpdateChecker.mm */,
AC518DFD201BB55A00EBC820 /* MGLTelemetryConfig.h */,
AC518DFE201BB55A00EBC820 /* MGLTelemetryConfig.m */,
+ 40834BA21FE05D3100C1BD0D /* Runtime */,
+ 40834BA11FE05CFD00C1BD0D /* Development */,
);
name = Telemetry;
sourceTree = "<group>";
@@ -1901,14 +2179,13 @@
DA88482C1CBAFA6200AB86E3 /* NSBundle+MGLAdditions.h in Headers */,
357FE2DD1E02D2B20068B753 /* NSCoder+MGLAdditions.h in Headers */,
35D13AB71D3D15E300AFB4E0 /* MGLStyleLayer.h in Headers */,
- 07D947531F67488E00E37934 /* MGLAbstractShapeSource_Private.h in Headers */,
+ 07D947531F67488E00E37934 /* MGLComputedShapeSource_Private.h in Headers */,
9654C1261FFC1AB900DB6A19 /* MGLPolyline_Private.h in Headers */,
40F887701D7A1E58008ECB67 /* MGLShapeSource_Private.h in Headers */,
350098DC1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h in Headers */,
DA8848231CBAFA6200AB86E3 /* MGLOfflineStorage_Private.h in Headers */,
404326891D5B9B27007111BD /* MGLAnnotationContainerView_Private.h in Headers */,
CA55CD41202C16AA00CE7095 /* MGLCameraChangeReason.h in Headers */,
- 1FB7DAAF1F2A4DBD00410606 /* MGLVectorSource+MGLAdditions.h in Headers */,
DA88483B1CBAFB8500AB86E3 /* MGLCalloutView.h in Headers */,
35E0CFE61D3E501500188327 /* MGLStyle_Private.h in Headers */,
3510FFF01D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */,
@@ -1919,10 +2196,9 @@
DA88485A1CBAFB9800AB86E3 /* MGLUserLocation_Private.h in Headers */,
966FCF531F3C322400F2B6DE /* MGLUserLocationHeadingArrowLayer.h in Headers */,
DA27C24F1CBB4C11000B0ECD /* MGLAccountManager_Private.h in Headers */,
- 07D947521F67488800E37934 /* MGLAbstractShapeSource.h in Headers */,
DA8847FC1CBAFA5100AB86E3 /* MGLStyle.h in Headers */,
DD9BE4F71EB263C50079A3AF /* UIViewController+MGLAdditions.h in Headers */,
- DAF0D8131DFE0EC500B28378 /* MGLVectorSource_Private.h in Headers */,
+ DAF0D8131DFE0EC500B28378 /* MGLVectorTileSource_Private.h in Headers */,
354B83961D2E873E005D9406 /* MGLUserLocationAnnotationView.h in Headers */,
DA8847F01CBAFA5100AB86E3 /* MGLAnnotation.h in Headers */,
400533011DB0862B0069F638 /* NSArray+MGLAdditions.h in Headers */,
@@ -1935,7 +2211,6 @@
FA68F14A1E9D656600F9F6C2 /* MGLFillExtrusionStyleLayer.h in Headers */,
353933FB1D3FB7C0003F57D7 /* MGLRasterStyleLayer.h in Headers */,
DA8847EF1CBAFA5100AB86E3 /* MGLAccountManager.h in Headers */,
- DA8848511CBAFB9800AB86E3 /* MGLAPIClient.h in Headers */,
DA35A2C91CCAAAD200E826B2 /* NSValue+MGLAdditions.h in Headers */,
3510FFEA1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.h in Headers */,
DA6408DB1DA4E7D300908C90 /* MGLVectorStyleLayer.h in Headers */,
@@ -1952,7 +2227,6 @@
071BBB031EE76146001FB02A /* MGLImageSource.h in Headers */,
DA8847F41CBAFA5100AB86E3 /* MGLOfflinePack.h in Headers */,
DA88482E1CBAFA6200AB86E3 /* NSException+MGLAdditions.h in Headers */,
- DA8848551CBAFB9800AB86E3 /* MGLLocationManager.h in Headers */,
96F3F73C1F57124B003E2D2C /* MGLUserLocationHeadingIndicator.h in Headers */,
408AA8571DAEDA1700022900 /* NSDictionary+MGLAdditions.h in Headers */,
DA88483F1CBAFB8500AB86E3 /* MGLUserLocation.h in Headers */,
@@ -1977,7 +2251,7 @@
DA8847F11CBAFA5100AB86E3 /* MGLGeometry.h in Headers */,
DA8848221CBAFA6200AB86E3 /* MGLOfflineRegion_Private.h in Headers */,
35136D4C1D4277FC00C20EFD /* MGLSource.h in Headers */,
- 3566C76C1D4A8DFA008152BC /* MGLRasterSource.h in Headers */,
+ 3566C76C1D4A8DFA008152BC /* MGLRasterTileSource.h in Headers */,
DA8847F91CBAFA5100AB86E3 /* MGLPolygon.h in Headers */,
4049C2AC1DB6E05500B3F799 /* MGLPointCollection_Private.h in Headers */,
DA8847F81CBAFA5100AB86E3 /* MGLPointAnnotation.h in Headers */,
@@ -2012,9 +2286,10 @@
DA8848841CBB033F00AB86E3 /* FABAttributes.h in Headers */,
DA8847FD1CBAFA5100AB86E3 /* MGLTilePyramidOfflineRegion.h in Headers */,
DA88482F1CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.h in Headers */,
+ DA9EA82B201C0C0C00F9874D /* NSExpression+MGLAdditions.h in Headers */,
DA8848601CBAFC2E00AB86E3 /* Mapbox.h in Headers */,
- DAF0D8101DFE0EA000B28378 /* MGLRasterSource_Private.h in Headers */,
- 350098BB1D480108004B2AF0 /* MGLVectorSource.h in Headers */,
+ DAF0D8101DFE0EA000B28378 /* MGLRasterTileSource_Private.h in Headers */,
+ 350098BB1D480108004B2AF0 /* MGLVectorTileSource.h in Headers */,
DA8847F61CBAFA5100AB86E3 /* MGLOfflineStorage.h in Headers */,
DAD1656E1CF41981001FF4B9 /* MGLFeature_Private.h in Headers */,
DA88483C1CBAFB8500AB86E3 /* MGLMapView.h in Headers */,
@@ -2026,22 +2301,22 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
- 96E516FE20005A4C00A02306 /* MGLLocationManager.h in Headers */,
556660CA1E1BF3A900E2C41B /* MGLFoundation.h in Headers */,
96E516ED200058A200A02306 /* MGLComputedShapeSource.h in Headers */,
35B82BF91D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h in Headers */,
96E5170020005A6100A02306 /* Fabric.h in Headers */,
DA35A2CA1CCAAAD200E826B2 /* NSValue+MGLAdditions.h in Headers */,
- 350098BC1D480108004B2AF0 /* MGLVectorSource.h in Headers */,
+ 350098BC1D480108004B2AF0 /* MGLVectorTileSource.h in Headers */,
FA68F14B1E9D656600F9F6C2 /* MGLFillExtrusionStyleLayer.h in Headers */,
96E516DE200054F700A02306 /* MGLGeometry_Private.h in Headers */,
353933FC1D3FB7C0003F57D7 /* MGLRasterStyleLayer.h in Headers */,
- 3566C76D1D4A8DFA008152BC /* MGLRasterSource.h in Headers */,
+ 3566C76D1D4A8DFA008152BC /* MGLRasterTileSource.h in Headers */,
DAED38641D62D0FC00D7640F /* NSURL+MGLAdditions.h in Headers */,
DABFB85E1CBE99E500D62B32 /* MGLAnnotation.h in Headers */,
DABFB8641CBE99E500D62B32 /* MGLOfflineStorage.h in Headers */,
96E516E32000552A00A02306 /* MGLAccountManager_Private.h in Headers */,
96E5170420005A6B00A02306 /* SMCalloutView.h in Headers */,
+ DA9EA82C201C0C0C00F9874D /* NSExpression+MGLAdditions.h in Headers */,
96036A02200565C700510F3D /* NSOrthography+MGLAdditions.h in Headers */,
DAD165791CF4CDFF001FF4B9 /* MGLShapeCollection.h in Headers */,
4049C29E1DB6CD6C00B3F799 /* MGLPointCollection.h in Headers */,
@@ -2065,7 +2340,7 @@
DAAF722E1DA903C700312FA4 /* MGLStyleValue_Private.h in Headers */,
DABFB8661CBE99E500D62B32 /* MGLPointAnnotation.h in Headers */,
96E5170220005A6600A02306 /* FABAttributes.h in Headers */,
- 96E516E42000560B00A02306 /* MGLAbstractShapeSource_Private.h in Headers */,
+ 96E516E42000560B00A02306 /* MGLComputedShapeSource_Private.h in Headers */,
96E516E92000560B00A02306 /* MGLAnnotationImage_Private.h in Headers */,
96E516E52000560B00A02306 /* MGLOfflinePack_Private.h in Headers */,
DD9BE4F91EB263D20079A3AF /* UIViewController+MGLAdditions.h in Headers */,
@@ -2091,7 +2366,6 @@
3510FFFA1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h in Headers */,
DA72620C1DEEE3480043BB89 /* MGLOpenGLStyleLayer.h in Headers */,
35CE61831D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */,
- 96E516EE2000590900A02306 /* MGLAbstractShapeSource.h in Headers */,
96E516F32000597100A02306 /* NSDictionary+MGLAdditions.h in Headers */,
96E516F02000595800A02306 /* NSBundle+MGLAdditions.h in Headers */,
96E516F920005A3500A02306 /* MGLFaux3DUserLocationAnnotationView.h in Headers */,
@@ -2118,14 +2392,14 @@
40F887711D7A1E59008ECB67 /* MGLShapeSource_Private.h in Headers */,
DABFB8631CBE99E500D62B32 /* MGLOfflineRegion.h in Headers */,
DA35A2B21CCA141D00E826B2 /* MGLCompassDirectionFormatter.h in Headers */,
- DAF0D8141DFE0EC500B28378 /* MGLVectorSource_Private.h in Headers */,
+ DAF0D8141DFE0EC500B28378 /* MGLVectorTileSource_Private.h in Headers */,
8989B17D201A48EB0081CF59 /* MGLHeatmapStyleLayer.h in Headers */,
DABFB8731CBE9A9900D62B32 /* Mapbox.h in Headers */,
357FE2DE1E02D2B20068B753 /* NSCoder+MGLAdditions.h in Headers */,
1753ED431E53CE6F00A9FD90 /* MGLConversion.h in Headers */,
DAC25FCD200FD83F009BE98E /* NSExpression+MGLPrivateAdditions.h in Headers */,
354B83971D2E873E005D9406 /* MGLUserLocationAnnotationView.h in Headers */,
- DAF0D8111DFE0EA000B28378 /* MGLRasterSource_Private.h in Headers */,
+ DAF0D8111DFE0EA000B28378 /* MGLRasterTileSource_Private.h in Headers */,
96E516FF20005A4F00A02306 /* MGLMapboxEvents.h in Headers */,
DABFB86B1CBE99E500D62B32 /* MGLTilePyramidOfflineRegion.h in Headers */,
968F36B51E4D128D003A5522 /* MGLDistanceFormatter.h in Headers */,
@@ -2153,7 +2427,6 @@
DAF0D8191DFE6B2800B28378 /* MGLAttributionInfo_Private.h in Headers */,
DABFB86A1CBE99E500D62B32 /* MGLStyle.h in Headers */,
DA00FC8F1D5EEB0D009AABC8 /* MGLAttributionInfo.h in Headers */,
- 96E516FD20005A4700A02306 /* MGLAPIClient.h in Headers */,
96E5170320005A6800A02306 /* FABKitProtocol.h in Headers */,
96E516E12000551100A02306 /* MGLMultiPoint_Private.h in Headers */,
3EA934623AD0000B7D99C3FB /* MGLRendererConfiguration.h in Headers */,
@@ -2176,6 +2449,7 @@
);
dependencies = (
165D0CE620005351009A3C66 /* PBXTargetDependency */,
+ CABE5DAC2072FA660003AF3C /* PBXTargetDependency */,
);
name = integration;
productName = "integration-tests";
@@ -2189,6 +2463,7 @@
16376B2B1FFDB4B40000563E /* Sources */,
16376B2C1FFDB4B40000563E /* Frameworks */,
16376B2D1FFDB4B40000563E /* Resources */,
+ CAA69DA6206DCD0E007279CD /* Embed Frameworks */,
);
buildRules = (
);
@@ -2396,6 +2671,8 @@
bg,
ar,
he,
+ da,
+ "pt-PT",
);
mainGroup = DA1DC9411CB6C1C2006E619F;
productRefGroup = DA1DC94B1CB6C1C2006E619F /* Products */;
@@ -2481,11 +2758,6 @@
DA8933F01CCD387900E68420 /* strip-frameworks.sh in Resources */,
DAC49C5C1CD02BC9009E1AA3 /* Localizable.stringsdict in Resources */,
DA8933BF1CCD2CAD00E68420 /* Foundation.stringsdict in Resources */,
- 40EA6BC11EF4599600FCCDA2 /* api_mapbox_com-digicert_2017.der in Resources */,
- 408982E91DEE208200754016 /* api_mapbox_staging.der in Resources */,
- 408982EA1DEE208B00754016 /* api_mapbox_com-digicert_2016.der in Resources */,
- 40EA6BC31EF4599D00FCCDA2 /* api_mapbox_com-geotrust_2017.der in Resources */,
- 408982EB1DEE209100754016 /* api_mapbox_com-geotrust_2016.der in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2497,12 +2769,7 @@
DA8933DB1CCD31D400E68420 /* Foundation.strings in Resources */,
960D0C371ECF5AAF008E151F /* Images.xcassets in Resources */,
DA8933DC1CCD31D400E68420 /* Foundation.stringsdict in Resources */,
- 40EA6BC41EF4599D00FCCDA2 /* api_mapbox_com-geotrust_2017.der in Resources */,
DAC49C5D1CD02BC9009E1AA3 /* Localizable.stringsdict in Resources */,
- 40599F0C1DEE1B7600182B5D /* api_mapbox_staging.der in Resources */,
- 40599F0D1DEE1B7A00182B5D /* api_mapbox_com-digicert_2016.der in Resources */,
- 40599F0E1DEE1B7E00182B5D /* api_mapbox_com-geotrust_2016.der in Resources */,
- 40EA6BC21EF4599700FCCDA2 /* api_mapbox_com-digicert_2017.der in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2527,6 +2794,7 @@
buildActionMask = 2147483647;
files = (
16376B0A1FFD9DAF0000563E /* MBGLIntegrationTests.m in Sources */,
+ CA0C27942076CA19001CE5B7 /* MGLMapViewIntegrationTest.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -2587,6 +2855,7 @@
1F95931D1E6DE2E900D5B294 /* MGLNSDateAdditionsTests.mm in Sources */,
DD58A4C61D822BD000E1F038 /* MGLExpressionTests.mm in Sources */,
3575798B1D502B0C000B822E /* MGLBackgroundStyleLayerTests.mm in Sources */,
+ 9658C155204761FC00D8A674 /* MGLMapViewScaleBarTests.m in Sources */,
409D0A0D1ED614CE00C95D0C /* MGLAnnotationViewIntegrationTests.swift in Sources */,
DA2E88621CC0382C00F24E7B /* MGLOfflinePackTests.m in Sources */,
55E2AD131E5B125400E8C587 /* MGLOfflineStorageTests.mm in Sources */,
@@ -2612,81 +2881,114 @@
files = (
35136D391D42271A00C20EFD /* MGLBackgroundStyleLayer.mm in Sources */,
3510FFEC1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm in Sources */,
+ 40834C431FE05F7500C1BD0D /* TSKSPKIHashCache.m in Sources */,
DAED38651D62D0FC00D7640F /* NSURL+MGLAdditions.m in Sources */,
+ 40834BEC1FE05E1800C1BD0D /* MMEEvent.m in Sources */,
9620BB3A1E69FE1700705A1D /* MGLSDKUpdateChecker.mm in Sources */,
354B83981D2E873E005D9406 /* MGLUserLocationAnnotationView.m in Sources */,
+ 40834BEE1FE05E1800C1BD0D /* MMEEventsConfiguration.m in Sources */,
DA88485D1CBAFB9800AB86E3 /* MGLFaux3DUserLocationAnnotationView.m in Sources */,
DAD165701CF41981001FF4B9 /* MGLFeature.mm in Sources */,
30E578191DAA855E0050F07E /* UIImage+MGLAdditions.mm in Sources */,
40EDA1C11CFE0E0500D9EA68 /* MGLAnnotationContainerView.m in Sources */,
+ 40834C481FE05F7500C1BD0D /* vendor_identifier.m in Sources */,
DA8848541CBAFB9800AB86E3 /* MGLCompactCalloutView.m in Sources */,
+ 40834BEB1FE05E1800C1BD0D /* MMEDependencyManager.m in Sources */,
+ 40834C411FE05F7500C1BD0D /* parse_configuration.m in Sources */,
DA8848251CBAFA6200AB86E3 /* MGLPointAnnotation.mm in Sources */,
+ 40834BEA1FE05E1800C1BD0D /* MMEConstants.m in Sources */,
929EFFAB1F56DCD4003A77D5 /* MGLAnnotationView.mm in Sources */,
35136D3C1D42272500C20EFD /* MGLCircleStyleLayer.mm in Sources */,
DD9BE4F81EB263C50079A3AF /* UIViewController+MGLAdditions.m in Sources */,
350098DE1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */,
DA6408DD1DA4E7D300908C90 /* MGLVectorStyleLayer.m in Sources */,
+ 40834BF71FE05E1800C1BD0D /* MMEUniqueIdentifier.m in Sources */,
3566C7681D4A77BA008152BC /* MGLShapeSource.mm in Sources */,
+ 40834C4A1FE05F7500C1BD0D /* TSKPinningValidator.m in Sources */,
400533021DB0862B0069F638 /* NSArray+MGLAdditions.mm in Sources */,
96036A03200565C700510F3D /* NSOrthography+MGLAdditions.m in Sources */,
+ 40834BF31FE05E1800C1BD0D /* MMETimerManager.m in Sources */,
35136D421D42274500C20EFD /* MGLRasterStyleLayer.mm in Sources */,
3538AA1F1D542239008EC33D /* MGLForegroundStyleLayer.mm in Sources */,
+ 40834BF11FE05E1800C1BD0D /* MMENSDateWrapper.m in Sources */,
+ 40834C461FE05F7500C1BD0D /* TSKPinFailureReport.m in Sources */,
+ 406E99B91FFEFF1B00D9FFCC /* MMEEventLogReportViewController.m in Sources */,
+ 40834BE61FE05E1800C1BD0D /* CLLocation+MMEMobileEvents.m in Sources */,
DA00FC901D5EEB0D009AABC8 /* MGLAttributionInfo.mm in Sources */,
DA88482D1CBAFA6200AB86E3 /* NSBundle+MGLAdditions.m in Sources */,
+ 406E99BB1FFF006C00D9FFCC /* MMEUINavigation.m in Sources */,
966FCF541F3C323300F2B6DE /* MGLUserLocationHeadingArrowLayer.m in Sources */,
+ 40834BE81FE05E1800C1BD0D /* MMECategoryLoader.m in Sources */,
DA88485B1CBAFB9800AB86E3 /* MGLUserLocation.m in Sources */,
927FBD011F4DB05500F8BF1F /* MGLMapSnapshotter.mm in Sources */,
- 350098BD1D480108004B2AF0 /* MGLVectorSource.mm in Sources */,
- 3566C76E1D4A8DFA008152BC /* MGLRasterSource.mm in Sources */,
+ 350098BD1D480108004B2AF0 /* MGLVectorTileSource.mm in Sources */,
+ 3566C76E1D4A8DFA008152BC /* MGLRasterTileSource.mm in Sources */,
DA88488C1CBB037E00AB86E3 /* SMCalloutView.m in Sources */,
35136D4E1D4277FC00C20EFD /* MGLSource.mm in Sources */,
1F06668D1EC64F8E001C16D7 /* MGLLight.mm in Sources */,
DA35A2B81CCA9A5D00E826B2 /* MGLClockDirectionFormatter.m in Sources */,
DAD1657A1CF4CDFF001FF4B9 /* MGLShapeCollection.mm in Sources */,
DAF25719201901E200367EF5 /* MGLHillshadeStyleLayer.mm in Sources */,
+ 40834BF51FE05E1800C1BD0D /* MMETypes.m in Sources */,
35136D451D42275100C20EFD /* MGLSymbolStyleLayer.mm in Sources */,
+ 40834C491FE05F7500C1BD0D /* TrustKit.m in Sources */,
35599DED1D46F14E0048254D /* MGLStyleValue.mm in Sources */,
DA8848211CBAFA6200AB86E3 /* MGLOfflinePack.mm in Sources */,
0778DD441F67556C00A73B34 /* MGLComputedShapeSource.mm in Sources */,
3557F7B21E1D27D300CCA5E6 /* MGLDistanceFormatter.m in Sources */,
+ 40834C4B1FE05F7500C1BD0D /* TSKPinningValidatorResult.m in Sources */,
+ 40834BE71FE05E1800C1BD0D /* MMEAPIClient.m in Sources */,
DA8848591CBAFB9800AB86E3 /* MGLMapView.mm in Sources */,
DA8848501CBAFB9800AB86E3 /* MGLAnnotationImage.m in Sources */,
+ 40834BF01FE05E1800C1BD0D /* MMELocationManager.m in Sources */,
DA8848281CBAFA6200AB86E3 /* MGLShape.mm in Sources */,
DA35A2B31CCA141D00E826B2 /* MGLCompassDirectionFormatter.m in Sources */,
DD0902A91DB1929D00C5BDCE /* MGLNetworkConfiguration.m in Sources */,
35D13AB91D3D15E300AFB4E0 /* MGLStyleLayer.mm in Sources */,
+ 40834C4C1FE05F7500C1BD0D /* TSKTrustKitConfig.m in Sources */,
DA35A2CB1CCAAAD200E826B2 /* NSValue+MGLAdditions.m in Sources */,
071BBB001EE7613F001FB02A /* MGLImageSource.mm in Sources */,
DA8848321CBAFA6200AB86E3 /* NSString+MGLAdditions.m in Sources */,
+ 40834C441FE05F7500C1BD0D /* reporting_utils.m in Sources */,
408AA8581DAEDA1E00022900 /* NSDictionary+MGLAdditions.mm in Sources */,
DA35A2A11CC9E95F00E826B2 /* MGLCoordinateFormatter.m in Sources */,
35305D481D22AA680007D005 /* NSData+MGLAdditions.mm in Sources */,
+ 40834BF61FE05E1800C1BD0D /* MMEUIApplicationWrapper.m in Sources */,
DA8848291CBAFA6200AB86E3 /* MGLStyle.mm in Sources */,
357FE2DF1E02D2B20068B753 /* NSCoder+MGLAdditions.mm in Sources */,
+ 40834BF81FE05E1800C1BD0D /* NSData+MMEGZIP.m in Sources */,
DA88481C1CBAFA6200AB86E3 /* MGLGeometry.mm in Sources */,
558DE7A21E5615E400C7916D /* MGLFoundation.mm in Sources */,
+ 40834BE91FE05E1800C1BD0D /* MMECommonEventData.m in Sources */,
3510FFF21D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm in Sources */,
DA88481F1CBAFA6200AB86E3 /* MGLMultiPoint.mm in Sources */,
DA88482B1CBAFA6200AB86E3 /* MGLTypes.m in Sources */,
FA68F14D1E9D656600F9F6C2 /* MGLFillExtrusionStyleLayer.mm in Sources */,
404C26E41D89B877000AA13D /* MGLTileSource.mm in Sources */,
- 07D947541F67489200E37934 /* MGLAbstractShapeSource.mm in Sources */,
355AE0011E9281DA00F3939D /* MGLScaleBar.mm in Sources */,
+ 40834C451FE05F7500C1BD0D /* TSKBackgroundReporter.m in Sources */,
DA88481D1CBAFA6200AB86E3 /* MGLMapCamera.mm in Sources */,
DACA86282019218600E9693A /* MGLRasterDEMSource.mm in Sources */,
DA8848261CBAFA6200AB86E3 /* MGLPolygon.mm in Sources */,
35B82BFA1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */,
- DA8848521CBAFB9800AB86E3 /* MGLAPIClient.m in Sources */,
+ 40834C401FE05F7500C1BD0D /* configuration_utils.m in Sources */,
+ 40834BF91FE05E1800C1BD0D /* MMEReachability.m in Sources */,
+ 40834BF21FE05E1800C1BD0D /* MMENSURLSessionWrapper.m in Sources */,
+ 40834C471FE05F7500C1BD0D /* TSKReportsRateLimiter.m in Sources */,
966FCF4E1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m in Sources */,
8989B17E201A48EB0081CF59 /* MGLHeatmapStyleLayer.mm in Sources */,
DA8848301CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.m in Sources */,
+ 40834BED1FE05E1800C1BD0D /* MMEEventLogger.m in Sources */,
353AFA161D65AB17005A69F4 /* NSDate+MGLAdditions.mm in Sources */,
+ 40834BF41FE05E1800C1BD0D /* MMETrustKitWrapper.m in Sources */,
+ 40834BEF1FE05E1800C1BD0D /* MMEEventsManager.m in Sources */,
35D13AC51D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm in Sources */,
DA8848241CBAFA6200AB86E3 /* MGLOfflineStorage.mm in Sources */,
DA88482A1CBAFA6200AB86E3 /* MGLTilePyramidOfflineRegion.mm in Sources */,
4049C29F1DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */,
35136D3F1D42273000C20EFD /* MGLLineStyleLayer.mm in Sources */,
DA704CC41F65A475004B3F28 /* MGLMapAccessibilityElement.mm in Sources */,
+ 40834C421FE05F7500C1BD0D /* ssl_pin_verifier.m in Sources */,
DA72620D1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm in Sources */,
DA88481A1CBAFA6200AB86E3 /* MGLAccountManager.m in Sources */,
3510FFFB1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */,
@@ -2694,7 +2996,6 @@
DA8848271CBAFA6200AB86E3 /* MGLPolyline.mm in Sources */,
DA8848581CBAFB9800AB86E3 /* MGLMapboxEvents.m in Sources */,
35CE61841D4165D9004F2359 /* UIColor+MGLAdditions.mm in Sources */,
- DA8848561CBAFB9800AB86E3 /* MGLLocationManager.m in Sources */,
3EA93369F61CF70AFA50465D /* MGLRendererConfiguration.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -2705,31 +3006,46 @@
files = (
35136D3A1D42271A00C20EFD /* MGLBackgroundStyleLayer.mm in Sources */,
3510FFED1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm in Sources */,
+ 40834C501FE05F7600C1BD0D /* TSKSPKIHashCache.m in Sources */,
354B83991D2E873E005D9406 /* MGLUserLocationAnnotationView.m in Sources */,
+ 40834C001FE05E1800C1BD0D /* MMEEvent.m in Sources */,
9620BB3B1E69FE1700705A1D /* MGLSDKUpdateChecker.mm in Sources */,
DAA4E4221CBB730400178DFB /* MGLPointAnnotation.mm in Sources */,
+ 40834C021FE05E1800C1BD0D /* MMEEventsConfiguration.m in Sources */,
DAED38661D62D0FC00D7640F /* NSURL+MGLAdditions.m in Sources */,
DAD165711CF41981001FF4B9 /* MGLFeature.mm in Sources */,
30E5781A1DAA855E0050F07E /* UIImage+MGLAdditions.mm in Sources */,
40EDA1C21CFE0E0500D9EA68 /* MGLAnnotationContainerView.m in Sources */,
+ 40834C551FE05F7600C1BD0D /* vendor_identifier.m in Sources */,
DAA4E4291CBB730400178DFB /* NSBundle+MGLAdditions.m in Sources */,
- DAA4E42E1CBB730400178DFB /* MGLAPIClient.m in Sources */,
+ 40834BFF1FE05E1800C1BD0D /* MMEDependencyManager.m in Sources */,
+ 40834C4E1FE05F7600C1BD0D /* parse_configuration.m in Sources */,
+ 40834BFE1FE05E1800C1BD0D /* MMEConstants.m in Sources */,
35136D3D1D42272500C20EFD /* MGLCircleStyleLayer.mm in Sources */,
DD9BE4FA1EB263F40079A3AF /* UIViewController+MGLAdditions.m in Sources */,
350098DF1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */,
DA6408DE1DA4E7D300908C90 /* MGLVectorStyleLayer.m in Sources */,
3566C7691D4A77BA008152BC /* MGLShapeSource.mm in Sources */,
+ 40834C0B1FE05E1800C1BD0D /* MMEUniqueIdentifier.m in Sources */,
400533031DB086490069F638 /* NSArray+MGLAdditions.mm in Sources */,
+ 40834C571FE05F7600C1BD0D /* TSKPinningValidator.m in Sources */,
35136D431D42274500C20EFD /* MGLRasterStyleLayer.mm in Sources */,
96036A04200565C700510F3D /* NSOrthography+MGLAdditions.m in Sources */,
+ 40834C071FE05E1800C1BD0D /* MMETimerManager.m in Sources */,
3538AA201D542239008EC33D /* MGLForegroundStyleLayer.mm in Sources */,
DA00FC911D5EEB0D009AABC8 /* MGLAttributionInfo.mm in Sources */,
+ 40834C051FE05E1800C1BD0D /* MMENSDateWrapper.m in Sources */,
+ 40834C531FE05F7600C1BD0D /* TSKPinFailureReport.m in Sources */,
+ 40834BFA1FE05E1800C1BD0D /* CLLocation+MMEMobileEvents.m in Sources */,
+ 406E99BA1FFEFF1B00D9FFCC /* MMEEventLogReportViewController.m in Sources */,
DAA4E4201CBB730400178DFB /* MGLOfflinePack.mm in Sources */,
966FCF551F3C323500F2B6DE /* MGLUserLocationHeadingArrowLayer.m in Sources */,
DAA4E4331CBB730400178DFB /* MGLUserLocation.m in Sources */,
+ 406E99BC1FFF006D00D9FFCC /* MMEUINavigation.m in Sources */,
+ 40834BFC1FE05E1800C1BD0D /* MMECategoryLoader.m in Sources */,
927FBD021F4DB05500F8BF1F /* MGLMapSnapshotter.mm in Sources */,
- 350098BE1D480108004B2AF0 /* MGLVectorSource.mm in Sources */,
- 3566C76F1D4A8DFA008152BC /* MGLRasterSource.mm in Sources */,
+ 350098BE1D480108004B2AF0 /* MGLVectorTileSource.mm in Sources */,
+ 3566C76F1D4A8DFA008152BC /* MGLRasterTileSource.mm in Sources */,
DAA4E4351CBB730400178DFB /* SMCalloutView.m in Sources */,
35136D4F1D4277FC00C20EFD /* MGLSource.mm in Sources */,
DA35A2B91CCA9A5D00E826B2 /* MGLClockDirectionFormatter.m in Sources */,
@@ -2737,27 +3053,36 @@
DAA4E4251CBB730400178DFB /* MGLShape.mm in Sources */,
35136D461D42275100C20EFD /* MGLSymbolStyleLayer.mm in Sources */,
DAF2571A201901E200367EF5 /* MGLHillshadeStyleLayer.mm in Sources */,
+ 40834C091FE05E1800C1BD0D /* MMETypes.m in Sources */,
35599DEE1D46F14E0048254D /* MGLStyleValue.mm in Sources */,
+ 40834C561FE05F7600C1BD0D /* TrustKit.m in Sources */,
DAA4E42B1CBB730400178DFB /* NSString+MGLAdditions.m in Sources */,
DAA4E4261CBB730400178DFB /* MGLStyle.mm in Sources */,
DAA32CC31E4C6B65006F8D24 /* MGLDistanceFormatter.m in Sources */,
DAA4E41D1CBB730400178DFB /* MGLGeometry.mm in Sources */,
+ 40834C581FE05F7600C1BD0D /* TSKPinningValidatorResult.m in Sources */,
+ 40834BFB1FE05E1800C1BD0D /* MMEAPIClient.m in Sources */,
DAA4E41F1CBB730400178DFB /* MGLMultiPoint.mm in Sources */,
DD0902AA1DB1929D00C5BDCE /* MGLNetworkConfiguration.m in Sources */,
+ 40834C041FE05E1800C1BD0D /* MMELocationManager.m in Sources */,
DA35A2B41CCA141D00E826B2 /* MGLCompassDirectionFormatter.m in Sources */,
35D13ABA1D3D15E300AFB4E0 /* MGLStyleLayer.mm in Sources */,
071BBAFF1EE7613E001FB02A /* MGLImageSource.mm in Sources */,
DA35A2CC1CCAAAD200E826B2 /* NSValue+MGLAdditions.m in Sources */,
+ 40834C591FE05F7600C1BD0D /* TSKTrustKitConfig.m in Sources */,
408AA8591DAEDA1E00022900 /* NSDictionary+MGLAdditions.mm in Sources */,
DAA4E4281CBB730400178DFB /* MGLTypes.m in Sources */,
DA35A2A21CC9E95F00E826B2 /* MGLCoordinateFormatter.m in Sources */,
+ 40834C511FE05F7600C1BD0D /* reporting_utils.m in Sources */,
35305D491D22AA680007D005 /* NSData+MGLAdditions.mm in Sources */,
357FE2E01E02D2B20068B753 /* NSCoder+MGLAdditions.mm in Sources */,
DAA4E42D1CBB730400178DFB /* MGLAnnotationImage.m in Sources */,
+ 40834C0A1FE05E1800C1BD0D /* MMEUIApplicationWrapper.m in Sources */,
558DE7A31E5615E400C7916D /* MGLFoundation.mm in Sources */,
3510FFF31D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm in Sources */,
- DAA4E4301CBB730400178DFB /* MGLLocationManager.m in Sources */,
+ 40834C0C1FE05E1800C1BD0D /* NSData+MMEGZIP.m in Sources */,
DAA4E4321CBB730400178DFB /* MGLMapView.mm in Sources */,
+ 40834BFD1FE05E1800C1BD0D /* MMECommonEventData.m in Sources */,
DAA4E41E1CBB730400178DFB /* MGLMapCamera.mm in Sources */,
FA68F14E1E9D656600F9F6C2 /* MGLFillExtrusionStyleLayer.mm in Sources */,
1F7454921ECBB42C00021D39 /* MGLLight.mm in Sources */,
@@ -2765,21 +3090,29 @@
355AE0021E9281DA00F3939D /* MGLScaleBar.mm in Sources */,
4018B1C81CDC287F00F666AF /* MGLAnnotationView.mm in Sources */,
07D8C6FB1F67560100381808 /* MGLComputedShapeSource.mm in Sources */,
+ 40834C521FE05F7600C1BD0D /* TSKBackgroundReporter.m in Sources */,
DAA4E4341CBB730400178DFB /* MGLFaux3DUserLocationAnnotationView.m in Sources */,
DACA86292019218600E9693A /* MGLRasterDEMSource.mm in Sources */,
35B82BFB1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */,
+ 40834C4D1FE05F7600C1BD0D /* configuration_utils.m in Sources */,
+ 40834C0D1FE05E1800C1BD0D /* MMEReachability.m in Sources */,
+ 40834C061FE05E1800C1BD0D /* MMENSURLSessionWrapper.m in Sources */,
+ 40834C541FE05F7600C1BD0D /* TSKReportsRateLimiter.m in Sources */,
DAA4E4311CBB730400178DFB /* MGLMapboxEvents.m in Sources */,
966FCF4F1F3A5C9200F2B6DE /* MGLUserLocationHeadingBeamLayer.m in Sources */,
DAA4E4231CBB730400178DFB /* MGLPolygon.mm in Sources */,
8989B17F201A48EB0081CF59 /* MGLHeatmapStyleLayer.mm in Sources */,
353AFA171D65AB17005A69F4 /* NSDate+MGLAdditions.mm in Sources */,
+ 40834C011FE05E1800C1BD0D /* MMEEventLogger.m in Sources */,
35D13AC61D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm in Sources */,
+ 40834C081FE05E1800C1BD0D /* MMETrustKitWrapper.m in Sources */,
+ 40834C031FE05E1800C1BD0D /* MMEEventsManager.m in Sources */,
DAA4E42A1CBB730400178DFB /* NSProcessInfo+MGLAdditions.m in Sources */,
DAA4E4211CBB730400178DFB /* MGLOfflineStorage.mm in Sources */,
4049C2A01DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */,
- 07D8C6FC1F67560400381808 /* MGLAbstractShapeSource.mm in Sources */,
35136D401D42273000C20EFD /* MGLLineStyleLayer.mm in Sources */,
DA704CC51F65A475004B3F28 /* MGLMapAccessibilityElement.mm in Sources */,
+ 40834C4F1FE05F7600C1BD0D /* ssl_pin_verifier.m in Sources */,
DA72620E1DEEE3480043BB89 /* MGLOpenGLStyleLayer.mm in Sources */,
DAA4E42F1CBB730400178DFB /* MGLCompactCalloutView.m in Sources */,
3510FFFC1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */,
@@ -2811,6 +3144,11 @@
target = DA8847D11CBAF91600AB86E3 /* dynamic */;
targetProxy = 165D0CE520005351009A3C66 /* PBXContainerItemProxy */;
};
+ CABE5DAC2072FA660003AF3C /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 16376B2E1FFDB4B40000563E /* Integration Test Harness */;
+ targetProxy = CABE5DAB2072FA660003AF3C /* PBXContainerItemProxy */;
+ };
DA25D5C81CCDA0C100607828 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = DA25D5B81CCD9EDE00607828 /* settings */;
@@ -2876,6 +3214,8 @@
DA3389651FA3EE1B001EA329 /* bg */,
DA80E9601FE84AD90065FC9B /* ar */,
DACBC60B20118ABE00C4D7E2 /* he */,
+ DAD88E07202ACFE800AAA536 /* da */,
+ DA93409B208562EB0059919A /* pt-PT */,
);
name = Localizable.strings;
sourceTree = "<group>";
@@ -2902,6 +3242,8 @@
DACCD9C81F1F473700BB09A1 /* hu */,
DA33896A1FA3EE58001EA329 /* bg */,
DACBC60E20118AFE00C4D7E2 /* he */,
+ DAD88E0C202AD06500AAA536 /* da */,
+ DA93409F208563440059919A /* pt-PT */,
);
name = Root.strings;
sourceTree = "<group>";
@@ -2926,6 +3268,8 @@
DA5C09BB1EFC486C0056B178 /* hu */,
DA3389681FA3EE48001EA329 /* bg */,
DACBC60D20118ADE00C4D7E2 /* he */,
+ DAD88E0A202AD03C00AAA536 /* da */,
+ DA93409D208563220059919A /* pt-PT */,
);
name = Localizable.strings;
sourceTree = "<group>";
@@ -2948,6 +3292,7 @@
DA33895F1FA3EAB7001EA329 /* pt-BR */,
DA3389661FA3EE28001EA329 /* bg */,
DACBC60C20118AD000C4D7E2 /* he */,
+ DAD88E08202AD01300AAA536 /* da */,
);
name = Foundation.strings;
sourceTree = "<group>";
@@ -2970,6 +3315,8 @@
DA3389671FA3EE2F001EA329 /* bg */,
DA33896B1FA3EF4A001EA329 /* hu */,
DA80E9611FE84AEF0065FC9B /* ar */,
+ DAD88E09202AD01F00AAA536 /* da */,
+ DA93409C2085630C0059919A /* pt-PT */,
);
name = Foundation.stringsdict;
sourceTree = "<group>";
@@ -2998,6 +3345,8 @@
DA704CBC1F637405004B3F28 /* uk */,
DA704CBD1F63746E004B3F28 /* zh-Hant */,
DA3389691FA3EE50001EA329 /* bg */,
+ DAD88E0B202AD04D00AAA536 /* da */,
+ DA93409E208563360059919A /* pt-PT */,
);
name = Localizable.stringsdict;
sourceTree = "<group>";
@@ -3328,6 +3677,7 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
+ GCC_PREFIX_HEADER = "$SRCROOT/src/Mapbox-Prefix.pch";
HEADER_SEARCH_PATHS = (
"$(mbgl_core_INCLUDE_DIRECTORIES)",
"$(mbgl_filesource_INCLUDE_DIRECTORIES)",
@@ -3370,6 +3720,7 @@
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
+ GCC_PREFIX_HEADER = "$SRCROOT/src/Mapbox-Prefix.pch";
HEADER_SEARCH_PATHS = (
"$(mbgl_core_INCLUDE_DIRECTORIES)",
"$(mbgl_filesource_INCLUDE_DIRECTORIES)",
diff --git a/platform/ios/jazzy.yml b/platform/ios/jazzy.yml
index 61e9ad39e8..34dcc1f50b 100644
--- a/platform/ios/jazzy.yml
+++ b/platform/ios/jazzy.yml
@@ -17,9 +17,9 @@ framework_root: ../darwin/src
custom_categories:
- name: Guides
children:
- - Adding Points to a Map
+ - Adding Markers to a Map
- Runtime Styling
- - Using Style Functions at Runtime
+ - Migrating to Expressions
- Working with Mapbox Studio
- Working with GeoJSON Data
- Predicates and Expressions
@@ -77,14 +77,13 @@ custom_categories:
- name: Style Content
children:
- MGLSource
- - MGLTileSource
- - MGLImageSource
- - MGLAbstractShapeSource
- MGLShapeSource
- MGLComputedShapeSource
- - MGLRasterSource
+ - MGLTileSource
+ - MGLRasterTileSource
- MGLRasterDEMSource
- - MGLVectorSource
+ - MGLVectorTileSource
+ - MGLImageSource
- name: Style Layers
children:
- MGLStyleLayer
diff --git a/platform/ios/resources/api_mapbox_com-digicert_2016.der b/platform/ios/resources/api_mapbox_com-digicert_2016.der
deleted file mode 100644
index e8ef427f33..0000000000
--- a/platform/ios/resources/api_mapbox_com-digicert_2016.der
+++ /dev/null
Binary files differ
diff --git a/platform/ios/resources/api_mapbox_com-digicert_2017.der b/platform/ios/resources/api_mapbox_com-digicert_2017.der
deleted file mode 100644
index 4a190085ab..0000000000
--- a/platform/ios/resources/api_mapbox_com-digicert_2017.der
+++ /dev/null
Binary files differ
diff --git a/platform/ios/resources/api_mapbox_com-geotrust_2016.der b/platform/ios/resources/api_mapbox_com-geotrust_2016.der
deleted file mode 100644
index 1c7331dedc..0000000000
--- a/platform/ios/resources/api_mapbox_com-geotrust_2016.der
+++ /dev/null
Binary files differ
diff --git a/platform/ios/resources/api_mapbox_com-geotrust_2017.der b/platform/ios/resources/api_mapbox_com-geotrust_2017.der
deleted file mode 100644
index 7bb9befbbf..0000000000
--- a/platform/ios/resources/api_mapbox_com-geotrust_2017.der
+++ /dev/null
Binary files differ
diff --git a/platform/ios/resources/api_mapbox_staging.der b/platform/ios/resources/api_mapbox_staging.der
deleted file mode 100644
index 45f7df7c49..0000000000
--- a/platform/ios/resources/api_mapbox_staging.der
+++ /dev/null
Binary files differ
diff --git a/platform/ios/resources/da.lproj/Localizable.strings b/platform/ios/resources/da.lproj/Localizable.strings
new file mode 100644
index 0000000000..dd384b21fc
--- /dev/null
+++ b/platform/ios/resources/da.lproj/Localizable.strings
@@ -0,0 +1,117 @@
+/* Accessibility hint */
+"ANNOTATION_A11Y_HINT" = "Vis mere info";
+
+/* No comment provided by engineer. */
+"API_CLIENT_400_DESC" = "Denne session kunne ikke gennemføres pga. data fejl. Den oprindelige forespørgsel var: %@";
+
+/* No comment provided by engineer. */
+"API_CLIENT_400_REASON" = "Status koden var %ld";
+
+/* No comment provided by engineer. */
+"CANCEL" = "Fortryd";
+
+/* Accessibility hint for closing the selected annotation’s callout view and returning to the map */
+"CLOSE_CALLOUT_A11Y_HINT" = "Retur til kortet";
+
+/* Accessibility hint */
+"COMPASS_A11Y_HINT" = "Fast nord";
+
+/* Accessibility label */
+"COMPASS_A11Y_LABEL" = "Kompas";
+
+/* Compass abbreviation for north */
+"COMPASS_NORTH" = "N";
+
+/* Instructions in Interface Builder designable; {key}, {plist file name} */
+"DESIGNABLE" = "For at vise et Mapbox-hosted kort her, angiv %1$@ til din access token i %2$@\n\nFor yderligere instruktion se:";
+
+/* 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" = "Vis credits, feedback formular med mere";
+
+/* Accessibility label */
+"INFO_A11Y_LABEL" = "Om kortet";
+
+/* List separator */
+"LIST_SEPARATOR" = ", ";
+
+/* User-friendly error description */
+"LOAD_MAP_FAILED_DESC" = "Kortet kunne ikke hentes på grund af en ukendt fejl";
+
+/* User-friendly error description */
+"LOAD_STYLE_FAILED_DESC" = "Kortet kunne ikke hentes på grund af en fejl i kort formatteringen";
+
+/* Accessibility label */
+"LOGO_A11Y_LABEL" = "Mapbox";
+
+/* Accessibility label */
+"MAP_A11Y_LABEL" = "Kort";
+
+/* Map accessibility value; {number of visible annotations} */
+"MAP_A11Y_VALUE_ANNOTATIONS" = "%ld synlige kommentarer.";
+
+/* Map accessibility value; {list of visible places} */
+"MAP_A11Y_VALUE_PLACES" = "Synlige steder: %@.";
+
+/* Map accessibility value; {number of visible roads} */
+"MAP_A11Y_VALUE_ROADS" = "%ld synlige veje.";
+
+/* Map accessibility value; {zoom level} */
+"MAP_A11Y_VALUE_ZOOM" = "Zoom %dx.";
+
+/* User-friendly error description */
+"PARSE_STYLE_FAILED_DESC" = "Kortet kunne ikke hentes på grund af en fejl";
+
+/* String format for accessibility value for road feature; {starting compass direction}, {ending compass direction} */
+"ROAD_DIRECTION_A11Y_FMT" = "%1$@ til %2$@";
+
+/* Accessibility value indicating that a road is a divided road (dual carriageway) */
+"ROAD_DIVIDED_A11Y_VALUE" = "Delt vej";
+
+/* Accessibility value indicating that a road is a one-way road */
+"ROAD_ONEWAY_A11Y_VALUE" = "Ensrettet";
+
+/* String format for accessibility value for road feature; {route number} */
+"ROAD_REF_A11Y_FMT" = "Rute %@";
+
+/* Action sheet title */
+"SDK_NAME" = "Mapbox Maps SDK for iOS";
+
+/* Developer-only SDK update notification; {latest version, in format x.x.x} */
+"SDK_UPDATE_AVAILABLE" = "Mapbox Maps SDK for iOS version %@ er nu tilgængelig:";
+
+/* User-friendly error description */
+"STYLE_NOT_FOUND_DESC" = "Kortet kunne ikke hentes fordi det enten ikke findes, eller ikke er kompatibelt.";
+
+/* Telemetry prompt message */
+"TELEMETRY_DISABLED_MSG" = "Du kan hjælpe med at gøre OpenStreetMap og Mapbox kort bedre ved at bidrage med annonyme bruger data.";
+
+/* Telemetry prompt button */
+"TELEMETRY_DISABLED_OFF" = "Deltag ikke";
+
+/* Telemetry prompt button */
+"TELEMETRY_DISABLED_ON" = "Deltag";
+
+/* Telemetry prompt message */
+"TELEMETRY_ENABLED_MSG" = "Du hjælper med at gøre OpenStreetMap og Mapbox kort bedre ved at bidrage med annonyme bruger data.";
+
+/* Telemetry prompt button */
+"TELEMETRY_ENABLED_OFF" = "Stop deltagelse";
+
+/* Telemetry prompt button */
+"TELEMETRY_ENABLED_ON" = "Fortsæt deltagelse";
+
+/* Telemetry prompt button */
+"TELEMETRY_MORE" = "Fortæl mig mere";
+
+/* Action in attribution sheet */
+"TELEMETRY_NAME" = "Mapbox Telemetry";
+
+/* Telemetry prompt title */
+"TELEMETRY_TITLE" = "Gør Mapbox kort bedre";
+
+/* Default user location annotation title */
+"USER_DOT_TITLE" = "Du er her";
+
diff --git a/platform/ios/resources/da.lproj/Localizable.stringsdict b/platform/ios/resources/da.lproj/Localizable.stringsdict
new file mode 100644
index 0000000000..296b8c88dd
--- /dev/null
+++ b/platform/ios/resources/da.lproj/Localizable.stringsdict
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>MAP_A11Y_VALUE_ANNOTATIONS</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@count@</string>
+ <key>count</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>ld</string>
+ <key>one</key>
+ <string>%ld synlig kommentar</string>
+ <key>other</key>
+ <string>%ld synlige kommentarer</string>
+ </dict>
+ </dict>
+ <key>MAP_A11Y_VALUE_ROADS</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@count@</string>
+ <key>count</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>ld</string>
+ <key>one</key>
+ <string>%ld synlig vej</string>
+ <key>other</key>
+ <string>%ld synlige veje</string>
+ </dict>
+ </dict>
+ <key>MAP_A11Y_VALUE_ZOOM</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@level@</string>
+ <key>level</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>Zoom %dx</string>
+ <key>other</key>
+ <string>Zoom %dx.</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/platform/ios/resources/pt-PT.lproj/Localizable.strings b/platform/ios/resources/pt-PT.lproj/Localizable.strings
new file mode 100644
index 0000000000..f9a072666b
--- /dev/null
+++ b/platform/ios/resources/pt-PT.lproj/Localizable.strings
Binary files differ
diff --git a/platform/ios/resources/pt-PT.lproj/Localizable.stringsdict b/platform/ios/resources/pt-PT.lproj/Localizable.stringsdict
new file mode 100644
index 0000000000..f342bd58b5
--- /dev/null
+++ b/platform/ios/resources/pt-PT.lproj/Localizable.stringsdict
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>MAP_A11Y_VALUE_ANNOTATIONS</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@count@</string>
+ <key>count</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>ld</string>
+ <key>one</key>
+ <string>%d erro reportado visível</string>
+ <key>other</key>
+ <string>%d erros reportados visíveis</string>
+ </dict>
+ </dict>
+ <key>MAP_A11Y_VALUE_ROADS</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@count@</string>
+ <key>count</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>ld</string>
+ <key>one</key>
+ <string>%d estrada visível</string>
+ <key>other</key>
+ <string>%d estradas visíveis</string>
+ </dict>
+ </dict>
+ <key>MAP_A11Y_VALUE_ZOOM</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@level@</string>
+ <key>level</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>Zoom %dx</string>
+ <key>other</key>
+ <string>Zoom %dx</string>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/platform/ios/resources/ru.lproj/Localizable.strings b/platform/ios/resources/ru.lproj/Localizable.strings
index 6d5ea9025e..b6ceffd520 100644
--- a/platform/ios/resources/ru.lproj/Localizable.strings
+++ b/platform/ios/resources/ru.lproj/Localizable.strings
@@ -1,44 +1,47 @@
/* Accessibility hint */
-"ANNOTATION_A11Y_HINT" = "Показать больше информации";
+"ANNOTATION_A11Y_HINT" = "Дополнительная информация";
/* No comment provided by engineer. */
-"API_CLIENT_400_DESC" = "The session data task failed. Original request was:%@";
+"API_CLIENT_400_DESC" = "Во время обмена данными произошла ошибка. Оригинал запроса: %@";
/* No comment provided by engineer. */
-"API_CLIENT_400_REASON" = "The status code was %ld";
+"API_CLIENT_400_REASON" = "Код ответа %ld";
/* No comment provided by engineer. */
"CANCEL" = "Отмена";
/* Accessibility hint for closing the selected annotation’s callout view and returning to the map */
-"CLOSE_CALLOUT_A11Y_HINT" = "Вернуться на карту";
+"CLOSE_CALLOUT_A11Y_HINT" = "Вернуться к карте";
/* Accessibility hint */
-"COMPASS_A11Y_HINT" = "Повернуть карту на север";
+"COMPASS_A11Y_HINT" = "Развернуть карту на север";
/* Accessibility label */
"COMPASS_A11Y_LABEL" = "Компас";
/* Compass abbreviation for north */
-"COMPASS_NORTH" = "N";
+"COMPASS_NORTH" = "С";
/* Instructions in Interface Builder designable; {key}, {plist file name} */
-"DESIGNABLE" = "Для отображения здесь карт Mapbox задайте %1$@ к вашему токену доступа в %2$@\n\nПодробные инструкции см.:";
+"DESIGNABLE" = "Для отображения здесь карт Mapbox, задайте %1$@ для вашего токена доступа в %2$@\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" = "Показать авторство, форму обратной связи и многое другое";
+"INFO_A11Y_HINT" = "Показать благодарности, форму отправки отзыва и другое";
/* Accessibility label */
"INFO_A11Y_LABEL" = "Об этой карте";
+/* List separator */
+"LIST_SEPARATOR" = ", ";
+
/* User-friendly error description */
"LOAD_MAP_FAILED_DESC" = "Не удалось загрузить карту из-за неизвестной ошибки.";
/* User-friendly error description */
-"LOAD_STYLE_FAILED_DESC" = "Не удалось загрузить карту так как невозможно загрузить стиль.";
+"LOAD_STYLE_FAILED_DESC" = "Не удалось загрузить карту из-за ошибки загрузки стиля.";
/* Accessibility label */
"LOGO_A11Y_LABEL" = "Mapbox";
@@ -46,23 +49,44 @@
/* Accessibility label */
"MAP_A11Y_LABEL" = "Карта";
-/* Map accessibility value */
-"MAP_A11Y_VALUE" = "Масштаб %1$dx\n%2$ld аннотации(й) видны";
+/* Map accessibility value; {number of visible annotations} */
+"MAP_A11Y_VALUE_ANNOTATIONS" = "Показано %ld аннотаций.";
+
+/* Map accessibility value; {list of visible places} */
+"MAP_A11Y_VALUE_PLACES" = "Показано мест: %@.";
+
+/* Map accessibility value; {number of visible roads} */
+"MAP_A11Y_VALUE_ROADS" = "Показано %ld дорог.";
+
+/* Map accessibility value; {zoom level} */
+"MAP_A11Y_VALUE_ZOOM" = "Масштаб %dx.";
/* User-friendly error description */
"PARSE_STYLE_FAILED_DESC" = "Не удалось загрузить карту из-за ошибки в стиле.";
+/* String format for accessibility value for road feature; {starting compass direction}, {ending compass direction} */
+"ROAD_DIRECTION_A11Y_FMT" = "%1$@ на %2$@";
+
+/* Accessibility value indicating that a road is a divided road (dual carriageway) */
+"ROAD_DIVIDED_A11Y_VALUE" = "Двусторонняя дорога";
+
+/* Accessibility value indicating that a road is a one-way road */
+"ROAD_ONEWAY_A11Y_VALUE" = "Односторонняя дорога";
+
+/* String format for accessibility value for road feature; {route number} */
+"ROAD_REF_A11Y_FMT" = "Трасса %@";
+
/* Action sheet title */
-"SDK_NAME" = "Mapbox Maps SDK for iOS";
+"SDK_NAME" = "Mapbox Maps SDK для iOS";
/* Developer-only SDK update notification; {latest version, in format x.x.x} */
-"SDK_UPDATE_AVAILABLE" = "Mapbox Maps SDK for iOS версии %@теперь доступен.";
+"SDK_UPDATE_AVAILABLE" = "Доступна версия Mapbox Maps SDK %@ для iOS:";
/* User-friendly error description */
-"STYLE_NOT_FOUND_DESC" = "Не удалось загрузить карту так как стиль не найден или несовместим.";
+"STYLE_NOT_FOUND_DESC" = "Не удалось загрузить карту, так как стиль не найден или несовместим.";
/* Telemetry prompt message */
-"TELEMETRY_DISABLED_MSG" = "Вы можете помочь сделать карты OpenStreetMap и Mapbox лучше путем предоставления анонимных данных об использовании.";
+"TELEMETRY_DISABLED_MSG" = "Вы поможете улучшить карты OpenStreetMap и Mapbox, предоставляя обезличенные данные об использовании.";
/* Telemetry prompt button */
"TELEMETRY_DISABLED_OFF" = "Не участвовать";
@@ -71,7 +95,7 @@
"TELEMETRY_DISABLED_ON" = "Участвовать";
/* Telemetry prompt message */
-"TELEMETRY_ENABLED_MSG" = "Вы помогаете сделать карты OpenStreetMap и Mapbox лучше путем предоставления анонимных данных об использовании.";
+"TELEMETRY_ENABLED_MSG" = "Вы помогаете улучшать карты OpenStreetMap и Mapbox, предоставляя обезличенные данные об использовании.";
/* Telemetry prompt button */
"TELEMETRY_ENABLED_OFF" = "Прекратить участие";
@@ -83,7 +107,7 @@
"TELEMETRY_MORE" = "Узнать больше";
/* Action in attribution sheet */
-"TELEMETRY_NAME" = "Mapbox телеметрия";
+"TELEMETRY_NAME" = "Телеметрия Mapbox";
/* Telemetry prompt title */
"TELEMETRY_TITLE" = "Сделать карты Mapbox лучше";
diff --git a/platform/ios/resources/ru.lproj/Localizable.stringsdict b/platform/ios/resources/ru.lproj/Localizable.stringsdict
index 81877703b1..fabd557780 100644
--- a/platform/ios/resources/ru.lproj/Localizable.stringsdict
+++ b/platform/ios/resources/ru.lproj/Localizable.stringsdict
@@ -2,26 +2,30 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <key>MAP_A11Y_VALUE</key>
+ <key>MAP_A11Y_VALUE_ANNOTATIONS</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
- <string>%#@level@
-%#@count@</string>
- <key>level</key>
+ <string>%#@count@</string>
+ <key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
- <string>d</string>
+ <string>ld</string>
<key>one</key>
- <string>Масштаб %dx</string>
+ <string>Показана %d аннотация</string>
<key>few</key>
- <string>Масштаб %dx</string>
+ <string>Показано %d аннотации</string>
<key>many</key>
- <string>Масштаб %dx</string>
+ <string>Показано %d аннотаций</string>
<key>other</key>
- <string>Масштаб %dx</string>
+ <string>Показано %d аннотаций</string>
</dict>
+ </dict>
+ <key>MAP_A11Y_VALUE_ROADS</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
@@ -29,13 +33,33 @@
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
- <string>%d аннотация видны</string>
+ <string>Показана %d дорога</string>
<key>few</key>
- <string>%d аннотации видны</string>
+ <string>Показано %d дороги</string>
<key>many</key>
- <string>%d аннотаций видны</string>
+ <string>Показано %d дорог</string>
<key>other</key>
- <string>%d аннотации видны</string>
+ <string>Показано %d дорог</string>
+ </dict>
+ </dict>
+ <key>MAP_A11Y_VALUE_ZOOM</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@level@</string>
+ <key>level</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>Масштаб %dx</string>
+ <key>few</key>
+ <string>Масштаб %dx</string>
+ <key>many</key>
+ <string>Масштаб %dx</string>
+ <key>other</key>
+ <string>Масштаб %dx</string>
</dict>
</dict>
</dict>
diff --git a/platform/ios/resources/sv.lproj/Localizable.stringsdict b/platform/ios/resources/sv.lproj/Localizable.stringsdict
index 90115bd803..5f44d19b37 100644
--- a/platform/ios/resources/sv.lproj/Localizable.stringsdict
+++ b/platform/ios/resources/sv.lproj/Localizable.stringsdict
@@ -2,22 +2,26 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
- <key>MAP_A11Y_VALUE</key>
+ <key>MAP_A11Y_VALUE_ANNOTATIONS</key>
<dict>
<key>NSStringLocalizedFormatKey</key>
- <string>%#@level@
-%#@count@</string>
- <key>level</key>
+ <string>%#@count@</string>
+ <key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
<string>NSStringPluralRuleType</string>
<key>NSStringFormatValueTypeKey</key>
- <string>d</string>
+ <string>ld</string>
<key>one</key>
- <string>Zoom %dx</string>
+ <string>%d annotering synlig</string>
<key>other</key>
- <string>Zoom %dx</string>
+ <string>%d annoteringar synliga</string>
</dict>
+ </dict>
+ <key>MAP_A11Y_VALUE_ROADS</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@count@</string>
<key>count</key>
<dict>
<key>NSStringFormatSpecTypeKey</key>
@@ -25,9 +29,25 @@
<key>NSStringFormatValueTypeKey</key>
<string>ld</string>
<key>one</key>
- <string>%d annotering synlig</string>
+ <string>%d väg synlig</string>
<key>other</key>
- <string>%d annoteringar synliga</string>
+ <string>%d vägar synliga</string>
+ </dict>
+ </dict>
+ <key>MAP_A11Y_VALUE_ZOOM</key>
+ <dict>
+ <key>NSStringLocalizedFormatKey</key>
+ <string>%#@level@</string>
+ <key>level</key>
+ <dict>
+ <key>NSStringFormatSpecTypeKey</key>
+ <string>NSStringPluralRuleType</string>
+ <key>NSStringFormatValueTypeKey</key>
+ <string>d</string>
+ <key>one</key>
+ <string>Zooma %dx</string>
+ <key>other</key>
+ <string>Zooma %dx</string>
</dict>
</dict>
</dict>
diff --git a/platform/ios/scripts/script_resources/MapboxDemo/MapboxDemo/ViewController.swift b/platform/ios/scripts/script_resources/MapboxDemo/MapboxDemo/ViewController.swift
index 34bbcb7666..d28b4e7d73 100644
--- a/platform/ios/scripts/script_resources/MapboxDemo/MapboxDemo/ViewController.swift
+++ b/platform/ios/scripts/script_resources/MapboxDemo/MapboxDemo/ViewController.swift
@@ -110,7 +110,7 @@ class ViewController: UIViewController {
// You can obtain your own access token from the
// [Mapbox account page](https://www.mapbox.com/studio/account/tokens/)
// and add it to this application's Info.plist as the value for MGLMapboxAccessToken
- if MGLAccountManager.accessToken() == "pk.eyJ1IjoibWFwYm94IiwiYSI6ImNqYThuNnZ3NTA5MGMyd3F1cmF1eW1xaGEifQ.TdBTSHHPeT1pfLZ_6x_1vA" {
+ if MGLAccountManager.accessToken == "pk.eyJ1IjoibWFwYm94IiwiYSI6ImNqYThuNnZ3NTA5MGMyd3F1cmF1eW1xaGEifQ.TdBTSHHPeT1pfLZ_6x_1vA" {
accessTokenWarningView.isHidden = false
}
diff --git a/platform/ios/src/MGLAPIClient.h b/platform/ios/src/MGLAPIClient.h
deleted file mode 100644
index 4e5ea3b5e0..0000000000
--- a/platform/ios/src/MGLAPIClient.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#import <Foundation/Foundation.h>
-
-#import "MGLMapboxEvents.h"
-#import "MGLTypes.h"
-
-NS_ASSUME_NONNULL_BEGIN
-
-@interface MGLAPIClient : NSObject <NSURLSessionDelegate>
-
-- (void)postEvents:(NS_ARRAY_OF(MGLMapboxEventAttributes *) *)events completionHandler:(nullable void (^)(NSError * _Nullable error))completionHandler;
-- (void)postEvent:(MGLMapboxEventAttributes *)event completionHandler:(nullable void (^)(NSError * _Nullable error))completionHandler;
-
-@end
-
-NS_ASSUME_NONNULL_END
diff --git a/platform/ios/src/MGLAPIClient.m b/platform/ios/src/MGLAPIClient.m
deleted file mode 100644
index 8a987d76d8..0000000000
--- a/platform/ios/src/MGLAPIClient.m
+++ /dev/null
@@ -1,202 +0,0 @@
-#import "MGLAPIClient.h"
-#import "NSBundle+MGLAdditions.h"
-#import "NSData+MGLAdditions.h"
-#import "MGLAccountManager.h"
-
-static NSString * const MGLAPIClientUserAgentBase = @"MapboxEventsiOS";
-static NSString * const MGLAPIClientBaseURL = @"https://events.mapbox.com";
-static NSString * const MGLAPIClientEventsPath = @"events/v2";
-
-static NSString * const MGLAPIClientHeaderFieldUserAgentKey = @"User-Agent";
-static NSString * const MGLAPIClientHeaderFieldContentTypeKey = @"Content-Type";
-static NSString * const MGLAPIClientHeaderFieldContentTypeValue = @"application/json";
-static NSString * const MGLAPIClientHeaderFieldContentEncodingKey = @"Content-Encoding";
-static NSString * const MGLAPIClientHTTPMethodPost = @"POST";
-
-@interface MGLAPIClient ()
-
-@property (nonatomic, copy) NSURLSession *session;
-@property (nonatomic, copy) NSURL *baseURL;
-@property (nonatomic, copy) NSData *digicertCert_2016;
-@property (nonatomic, copy) NSData *geoTrustCert_2016;
-@property (nonatomic, copy) NSData *digicertCert_2017;
-@property (nonatomic, copy) NSData *geoTrustCert_2017;
-@property (nonatomic, copy) NSData *testServerCert;
-@property (nonatomic, copy) NSString *userAgent;
-@property (nonatomic) BOOL usesTestServer;
-
-@end
-
-@implementation MGLAPIClient
-
-- (instancetype)init {
- self = [super init];
- if (self) {
- _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
- delegate:self delegateQueue:nil];
- [self loadCertificates];
- [self setupBaseURL];
- [self setupUserAgent];
- }
- return self;
-}
-
-#pragma mark Public API
-
-- (void)postEvents:(nonnull NS_ARRAY_OF(MGLMapboxEventAttributes *) *)events completionHandler:(nullable void (^)(NSError * _Nullable error))completionHandler {
- __block NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:[self requestForEvents:events]
- completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
- NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
- NSError *statusError = nil;
- if (httpResponse.statusCode >= 400) {
- NSString *description = [NSString stringWithFormat:NSLocalizedStringWithDefaultValue(@"API_CLIENT_400_DESC", nil, nil, @"The session data task failed. Original request was: %@", nil), dataTask.originalRequest];
- NSString *reason = [NSString stringWithFormat:NSLocalizedStringWithDefaultValue(@"API_CLIENT_400_REASON", nil, nil, @"The status code was %ld", nil), (long)httpResponse.statusCode];
- NSDictionary *userInfo = @{NSLocalizedDescriptionKey: description,
- NSLocalizedFailureReasonErrorKey: reason};
- statusError = [NSError errorWithDomain:MGLErrorDomain code:1 userInfo:userInfo];
- }
- if (completionHandler) {
- error = error ?: statusError;
- completionHandler(error);
- }
- dataTask = nil;
- }];
- [dataTask resume];
-}
-
-- (void)postEvent:(nonnull MGLMapboxEventAttributes *)event completionHandler:(nullable void (^)(NSError * _Nullable error))completionHandler {
- [self postEvents:@[event] completionHandler:completionHandler];
-}
-
-#pragma mark Utilities
-
-- (NSURLRequest *)requestForEvents:(NS_ARRAY_OF(MGLMapboxEventAttributes *) *)events {
- NSString *path = [NSString stringWithFormat:@"%@?access_token=%@", MGLAPIClientEventsPath, [MGLAccountManager accessToken]];
- NSURL *url = [NSURL URLWithString:path relativeToURL:self.baseURL];
- NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
- [request setValue:self.userAgent forHTTPHeaderField:MGLAPIClientHeaderFieldUserAgentKey];
- [request setValue:MGLAPIClientHeaderFieldContentTypeValue forHTTPHeaderField:MGLAPIClientHeaderFieldContentTypeKey];
- [request setHTTPMethod:MGLAPIClientHTTPMethodPost];
-
- NSData *jsonData = [self serializedDataForEvents:events];
-
- // Compressing less than 3 events can have a negative impact on the size.
- if (events.count > 2) {
- NSData *compressedData = [jsonData mgl_compressedData];
- [request setValue:@"deflate" forHTTPHeaderField:MGLAPIClientHeaderFieldContentEncodingKey];
- [request setHTTPBody:compressedData];
- }
-
- // Set JSON data if events.count were less than 3 or something went wrong with compressing HTTP body data.
- if (!request.HTTPBody) {
- [request setValue:nil forHTTPHeaderField:MGLAPIClientHeaderFieldContentEncodingKey];
- [request setHTTPBody:jsonData];
- }
-
- return [request copy];
-}
-
-- (void)setupBaseURL {
- NSString *testServerURLString = [[NSUserDefaults standardUserDefaults] stringForKey:@"MGLTelemetryTestServerURL"];
- NSURL *testServerURL = [NSURL URLWithString:testServerURLString];
- if (testServerURL && [testServerURL.scheme isEqualToString:@"https"]) {
- self.baseURL = testServerURL;
- self.usesTestServer = YES;
- } else {
- self.baseURL = [NSURL URLWithString:MGLAPIClientBaseURL];
- }
-}
-
-- (void)loadCertificates {
- NSData *certificate;
- [self loadCertificate:&certificate withResource:@"api_mapbox_com-geotrust_2016"];
- self.geoTrustCert_2016 = certificate;
- [self loadCertificate:&certificate withResource:@"api_mapbox_com-digicert_2016"];
- self.digicertCert_2016 = certificate;
- [self loadCertificate:&certificate withResource:@"api_mapbox_com-geotrust_2017"];
- self.geoTrustCert_2017 = certificate;
- [self loadCertificate:&certificate withResource:@"api_mapbox_com-digicert_2017"];
- self.digicertCert_2017 = certificate;
- [self loadCertificate:&certificate withResource:@"api_mapbox_staging"];
- self.testServerCert = certificate;
-}
-
-- (void)loadCertificate:(NSData **)certificate withResource:(NSString *)resource {
- NSBundle *frameworkBundle = [NSBundle mgl_frameworkBundle];
- NSString *cerPath = [frameworkBundle pathForResource:resource ofType:@"der"];
- if (cerPath != nil) {
- *certificate = [NSData dataWithContentsOfFile:cerPath];
- }
-}
-
-- (void)setupUserAgent {
- NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIdentifier"];
- NSString *appVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"];
- NSString *appBuildNumber = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
- NSString *semanticVersion = [NSBundle mgl_frameworkInfoDictionary][@"MGLSemanticVersionString"];
- NSString *shortVersion = [NSBundle mgl_frameworkInfoDictionary][@"CFBundleShortVersionString"];
- NSString *sdkVersion = semanticVersion ?: shortVersion;
- _userAgent = [NSString stringWithFormat:@"%@/%@/%@ %@/%@", appName, appVersion, appBuildNumber, MGLAPIClientUserAgentBase, sdkVersion];
-}
-
-#pragma mark - JSON Serialization
-
-- (NSData *)serializedDataForEvents:(NS_ARRAY_OF(MGLMapboxEventAttributes *) *)events {
- return [NSJSONSerialization dataWithJSONObject:events options:0 error:nil];
-}
-
-#pragma mark NSURLSessionDelegate
-
-- (BOOL)evaluateCertificateWithCertificateData:(NSData *)certificateData keyCount:(CFIndex)keyCount serverTrust:(SecTrustRef)serverTrust challenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^) (NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
- for (int lc = 0; lc < keyCount; lc++) {
- SecCertificateRef certificate = SecTrustGetCertificateAtIndex(serverTrust, lc);
- NSData *remoteCertificateData = CFBridgingRelease(SecCertificateCopyData(certificate));
- if ([remoteCertificateData isEqualToData:certificateData]) {
- completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
- return YES;
- }
- }
- return NO;
-}
-
-- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^) (NSURLSessionAuthChallengeDisposition disposition, NSURLCredential *credential))completionHandler {
-
- if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
- SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
- SecTrustResultType trustResult;
-
- // Validate the certificate chain with the device's trust store anyway this *might* use revocation checking
- SecTrustEvaluate(serverTrust, &trustResult);
-
- BOOL found = NO; // For clarity; we start in a state where the challange has not been completed and no certificate has been found
-
- if (trustResult == kSecTrustResultUnspecified) {
- // Look for a pinned certificate in the server's certificate chain
- CFIndex numKeys = SecTrustGetCertificateCount(serverTrust);
-
- // Check certs in the following order: digicert 2016, digicert 2017, geotrust 2016, geotrust 2017
- found = [self evaluateCertificateWithCertificateData:self.digicertCert_2016 keyCount:numKeys serverTrust:serverTrust challenge:challenge completionHandler:completionHandler];
- if (!found) {
- found = [self evaluateCertificateWithCertificateData:self.digicertCert_2017 keyCount:numKeys serverTrust:serverTrust challenge:challenge completionHandler:completionHandler];
- }
- if (!found) {
- found = [self evaluateCertificateWithCertificateData:self.geoTrustCert_2016 keyCount:numKeys serverTrust:serverTrust challenge:challenge completionHandler:completionHandler];
- }
- if (!found) {
- found = [self evaluateCertificateWithCertificateData:self.geoTrustCert_2017 keyCount:numKeys serverTrust:serverTrust challenge:challenge completionHandler:completionHandler];
- }
-
- // If challenge can't be completed with any of the above certs, then try the test server if the app is configured to use the test server
- if (!found && _usesTestServer) {
- found = [self evaluateCertificateWithCertificateData:self.testServerCert keyCount:numKeys serverTrust:serverTrust challenge:challenge completionHandler:completionHandler];
- }
- }
-
- if (!found) {
- // No certificate was found so cancel the connection.
- completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust]);
- }
- }
-}
-
-@end
diff --git a/platform/ios/src/MGLAnnotationView.h b/platform/ios/src/MGLAnnotationView.h
index 8006ec3e40..57d97e56c1 100644
--- a/platform/ios/src/MGLAnnotationView.h
+++ b/platform/ios/src/MGLAnnotationView.h
@@ -169,12 +169,12 @@ MGL_EXPORT
value of this property is `NO` or the map’s pitch is zero, the annotation view
remains the same size regardless of its position on-screen.
- The default value of this property is `YES`. Set this property to `NO` if the
- view’s legibility is important.
+ The default value of this property is `NO`. Keep this property set to `NO` if
+ the view’s legibility is important.
@note Scaling many on-screen annotation views can contribute to poor map
- performance. Consider disabling this property if your use case involves
- hundreds or thousands of annotation views.
+ performance. Consider keeping this property disabled if your use case
+ involves hundreds or thousands of annotation views.
*/
@property (nonatomic, assign) BOOL scalesWithViewingDistance;
diff --git a/platform/ios/src/MGLAnnotationView.mm b/platform/ios/src/MGLAnnotationView.mm
index 4585479582..1c53ba507a 100644
--- a/platform/ios/src/MGLAnnotationView.mm
+++ b/platform/ios/src/MGLAnnotationView.mm
@@ -45,7 +45,7 @@
_lastAppliedScaleTransform = CATransform3DIdentity;
_annotation = annotation;
_reuseIdentifier = [reuseIdentifier copy];
- _scalesWithViewingDistance = YES;
+ _scalesWithViewingDistance = NO;
_enabled = YES;
}
diff --git a/platform/ios/src/MGLCalloutView.h b/platform/ios/src/MGLCalloutView.h
index 0481a39680..689b159fd7 100644
--- a/platform/ios/src/MGLCalloutView.h
+++ b/platform/ios/src/MGLCalloutView.h
@@ -39,7 +39,14 @@ NS_ASSUME_NONNULL_BEGIN
Presents a callout view by adding it to `view` and pointing at the given rect
of `view`’s bounds. Constrains the callout to the bounds of the given view.
*/
-- (void)presentCalloutFromRect:(CGRect)rect inView:(UIView *)view constrainedToView:(UIView *)constrainedView animated:(BOOL)animated;
+- (void)presentCalloutFromRect:(CGRect)rect inView:(UIView *)view constrainedToView:(UIView *)constrainedView animated:(BOOL)animated __attribute__((unavailable("Use -presentCalloutFromRect:inView:constrainedToRect:animated: instead.")));
+
+
+/**
+ Presents a callout view by adding it to `view` and pointing at the given rect
+ of `view`’s bounds. Constrains the callout to the rect in the space of `view`.
+ */
+- (void)presentCalloutFromRect:(CGRect)rect inView:(UIView *)view constrainedToRect:(CGRect)constrainedRect animated:(BOOL)animated;
/**
Dismisses the callout view.
@@ -49,6 +56,24 @@ NS_ASSUME_NONNULL_BEGIN
@optional
/**
+ If implemented, should provide margins to expand the rect the callout is presented from.
+
+ These are used to determine positioning. Currently only the top and bottom properties of the return
+ value are used. For example, `{ .top = -50.0, .left = -10.0, .bottom = 0.0, .right = -10.0 }` indicates
+ a 50 point margin above the presentation origin rect (and 10 point margins to the left and the right)
+ in which the callout is assumed to be displayed.
+
+ There are no assumed defaults for these margins, as they should be calculated from the callout that
+ is to be presented. For example, `SMCalloutView` generates the top margin from the callout height, but
+ the left and right margins from a minimum width that the callout should have.
+
+ @param rect Rect that the callout is presented from. This should be the same as the one passed in
+ `-[MGLCalloutView presentCalloutFromRect:inView:constrainedToRect:animated:]`
+ @return `UIEdgeInsets` representing the margins. Values should be negative.
+ */
+- (UIEdgeInsets)marginInsetsHintForPresentationFromRect:(CGRect)rect NS_SWIFT_NAME(marginInsetsHintForPresentation(from:));
+
+/**
A Boolean value indicating whether the callout view should be anchored to
the corresponding annotation. You can adjust the callout view’s precise location by
overriding -[UIView setCenter:]. The callout view will not be anchored to the
diff --git a/platform/ios/src/MGLLocationManager.h b/platform/ios/src/MGLLocationManager.h
deleted file mode 100644
index ea23801813..0000000000
--- a/platform/ios/src/MGLLocationManager.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#import <Foundation/Foundation.h>
-#import <CoreLocation/CoreLocation.h>
-
-@protocol MGLLocationManagerDelegate;
-
-@interface MGLLocationManager : NSObject <CLLocationManagerDelegate>
-
-@property (nonatomic, weak) id<MGLLocationManagerDelegate> delegate;
-
-- (void)startUpdatingLocation;
-- (void)stopUpdatingLocation;
-
-@end
-
-@protocol MGLLocationManagerDelegate <NSObject>
-
-@optional
-
-- (void)locationManager:(MGLLocationManager *)locationManager didUpdateLocations:(NSArray *)locations;
-- (void)locationManagerDidStartLocationUpdates:(MGLLocationManager *)locationManager;
-- (void)locationManagerBackgroundLocationUpdatesDidTimeout:(MGLLocationManager *)locationManager;
-- (void)locationManagerBackgroundLocationUpdatesDidAutomaticallyPause:(MGLLocationManager *)locationManager;
-- (void)locationManagerDidStopLocationUpdates:(MGLLocationManager *)locationManager;
-
-@end
diff --git a/platform/ios/src/MGLLocationManager.m b/platform/ios/src/MGLLocationManager.m
deleted file mode 100644
index 85ef4ca489..0000000000
--- a/platform/ios/src/MGLLocationManager.m
+++ /dev/null
@@ -1,175 +0,0 @@
-#import "MGLLocationManager.h"
-#import "MGLTelemetryConfig.h"
-#import <UIKit/UIKit.h>
-
-static const NSTimeInterval MGLLocationManagerHibernationTimeout = 300.0;
-static const NSTimeInterval MGLLocationManagerHibernationPollInterval = 5.0;
-static const CLLocationDistance MGLLocationManagerDistanceFilter = 5.0;
-static NSString * const MGLLocationManagerRegionIdentifier = @"MGLLocationManagerRegionIdentifier.fence.center";
-
-@interface MGLLocationManager ()
-
-@property (nonatomic) CLLocationManager *standardLocationManager;
-@property (nonatomic) BOOL hostAppHasBackgroundCapability;
-@property (nonatomic, getter=isUpdatingLocation) BOOL updatingLocation;
-@property (nonatomic) NSDate *backgroundLocationServiceTimeoutAllowedDate;
-@property (nonatomic) NSTimer *backgroundLocationServiceTimeoutTimer;
-
-@end
-
-@implementation MGLLocationManager
-
-- (instancetype)init {
- self = [super init];
- if (self) {
- NSArray *backgroundModes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UIBackgroundModes"];
- _hostAppHasBackgroundCapability = [backgroundModes containsObject:@"location"];
- }
- return self;
-}
-
-- (void)startUpdatingLocation {
- if ([self isUpdatingLocation]) {
- return;
- }
-
- [self configurePassiveStandardLocationManager];
- [self startLocationServices];
-}
-
-- (void)stopUpdatingLocation {
- if ([self isUpdatingLocation]) {
- [self.standardLocationManager stopUpdatingLocation];
- [self.standardLocationManager stopMonitoringSignificantLocationChanges];
- self.updatingLocation = NO;
- if ([self.delegate respondsToSelector:@selector(locationManagerDidStopLocationUpdates:)]) {
- [self.delegate locationManagerDidStopLocationUpdates:self];
- }
- }
- if(self.standardLocationManager.monitoredRegions.count > 0) {
- for(CLRegion *region in self.standardLocationManager.monitoredRegions) {
- if([region.identifier isEqualToString:MGLLocationManagerRegionIdentifier]) {
- [self.standardLocationManager stopMonitoringForRegion:region];
- }
- }
- }
-}
-
-#pragma mark - Utilities
-
-- (void)configurePassiveStandardLocationManager {
- if (!self.standardLocationManager) {
- CLLocationManager *standardLocationManager = [[CLLocationManager alloc] init];
- standardLocationManager.delegate = self;
- standardLocationManager.desiredAccuracy = kCLLocationAccuracyThreeKilometers;
- standardLocationManager.distanceFilter = MGLLocationManagerDistanceFilter;
- self.standardLocationManager = standardLocationManager;
- }
-}
-
-- (void)startLocationServices {
- CLAuthorizationStatus authorizationStatus = [CLLocationManager authorizationStatus];
-#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000
- BOOL authorizedAlways = authorizationStatus == kCLAuthorizationStatusAuthorizedAlways;
-#else
- BOOL authorizedAlways = authorizationStatus == kCLAuthorizationStatusAuthorized;
-#endif
- if (authorizedAlways || authorizationStatus == kCLAuthorizationStatusAuthorizedWhenInUse) {
- // If the host app can run in the background with `always` location permissions then allow background
- // updates and start the significant location change service and background timeout timer
- if (self.hostAppHasBackgroundCapability && authorizedAlways) {
- [self.standardLocationManager startMonitoringSignificantLocationChanges];
- [self startBackgroundTimeoutTimer];
- // On iOS 9 and above also allow background location updates
- if ([self.standardLocationManager respondsToSelector:@selector(allowsBackgroundLocationUpdates)]) {
- self.standardLocationManager.allowsBackgroundLocationUpdates = YES;
- }
- }
-
- [self.standardLocationManager startUpdatingLocation];
- self.updatingLocation = YES;
- if ([self.delegate respondsToSelector:@selector(locationManagerDidStartLocationUpdates:)]) {
- [self.delegate locationManagerDidStartLocationUpdates:self];
- }
- }
-}
-
-- (void)timeoutAllowedCheck {
- if (self.backgroundLocationServiceTimeoutAllowedDate == nil) {
- return;
- }
-
- if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive ||
- [UIApplication sharedApplication].applicationState == UIApplicationStateInactive ) {
- [self startBackgroundTimeoutTimer];
- return;
- }
-
- NSTimeInterval timeIntervalSinceTimeoutAllowed = [[NSDate date] timeIntervalSinceDate:self.backgroundLocationServiceTimeoutAllowedDate];
- if (timeIntervalSinceTimeoutAllowed > 0) {
- [self.standardLocationManager stopUpdatingLocation];
- self.backgroundLocationServiceTimeoutAllowedDate = nil;
- if ([self.delegate respondsToSelector:@selector(locationManagerBackgroundLocationUpdatesDidTimeout:)]) {
- [self.delegate locationManagerBackgroundLocationUpdatesDidTimeout:self];
- }
- }
-}
-
-- (void)startBackgroundTimeoutTimer {
- [self.backgroundLocationServiceTimeoutTimer invalidate];
- self.backgroundLocationServiceTimeoutAllowedDate = [[NSDate date] dateByAddingTimeInterval:MGLLocationManagerHibernationTimeout];
- self.backgroundLocationServiceTimeoutTimer = [NSTimer scheduledTimerWithTimeInterval:MGLLocationManagerHibernationPollInterval target:self selector:@selector(timeoutAllowedCheck) userInfo:nil repeats:YES];
-}
-
-- (void)establishRegionMonitoringForLocation:(CLLocation *)location {
- CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:location.coordinate radius:MGLTelemetryConfig.sharedConfig.MGLLocationManagerHibernationRadius identifier:MGLLocationManagerRegionIdentifier];
- region.notifyOnEntry = NO;
- region.notifyOnExit = YES;
- [self.standardLocationManager startMonitoringForRegion:region];
-}
-
-#pragma mark - CLLocationManagerDelegate
-
-- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status {
- switch (status) {
-#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 80000
- case kCLAuthorizationStatusAuthorizedAlways:
-#else
- case kCLAuthorizationStatusAuthorized:
-#endif
- case kCLAuthorizationStatusAuthorizedWhenInUse:
- [self startUpdatingLocation];
- break;
- default:
- [self stopUpdatingLocation];
- break;
- }
-}
-
-- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
- CLLocation *location = locations.lastObject;
- if (location.speed > 0.0) {
- [self startBackgroundTimeoutTimer];
- }
- if (self.standardLocationManager.monitoredRegions.count == 0 || location.horizontalAccuracy < MGLTelemetryConfig.sharedConfig.MGLLocationManagerHibernationRadius) {
- [self establishRegionMonitoringForLocation:location];
- }
- if ([self.delegate respondsToSelector:@selector(locationManager:didUpdateLocations:)]) {
- [self.delegate locationManager:self didUpdateLocations:locations];
- }
-}
-
-- (void)locationManager:(CLLocationManager *)manager didExitRegion:(CLRegion *)region {
- [self startBackgroundTimeoutTimer];
- [self.standardLocationManager startUpdatingLocation];
-}
-
-- (void)locationManagerDidPauseLocationUpdates:(CLLocationManager *)manager {
- if ([UIApplication sharedApplication].applicationState == UIApplicationStateBackground) {
- if ([self.delegate respondsToSelector:@selector(locationManagerBackgroundLocationUpdatesDidAutomaticallyPause:)]) {
- [self.delegate locationManagerBackgroundLocationUpdatesDidAutomaticallyPause:self];
- }
- }
-}
-
-@end
diff --git a/platform/ios/src/MGLMapAccessibilityElement.mm b/platform/ios/src/MGLMapAccessibilityElement.mm
index 79dcda4054..8bce38a145 100644
--- a/platform/ios/src/MGLMapAccessibilityElement.mm
+++ b/platform/ios/src/MGLMapAccessibilityElement.mm
@@ -4,7 +4,7 @@
#import "MGLFeature.h"
#import "MGLGeometry_Private.h"
-#import "MGLVectorSource_Private.h"
+#import "MGLVectorTileSource_Private.h"
#import "NSBundle+MGLAdditions.h"
#import "NSOrthography+MGLAdditions.h"
@@ -48,7 +48,7 @@
if (self = [super initWithAccessibilityContainer:container]) {
_feature = feature;
- NSString *languageCode = [MGLVectorSource preferredMapboxStreetsLanguage];
+ NSString *languageCode = [MGLVectorTileSource preferredMapboxStreetsLanguage];
NSString *nameAttribute = [NSString stringWithFormat:@"name_%@", languageCode];
NSString *name = [feature attributeForKey:nameAttribute];
diff --git a/platform/ios/src/MGLMapView+IBAdditions.h b/platform/ios/src/MGLMapView+IBAdditions.h
index 6d5351df2b..64016e8319 100644
--- a/platform/ios/src/MGLMapView+IBAdditions.h
+++ b/platform/ios/src/MGLMapView+IBAdditions.h
@@ -44,6 +44,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic) IBInspectable BOOL allowsTilting;
@property (nonatomic) IBInspectable BOOL showsUserLocation;
@property (nonatomic) IBInspectable BOOL showsHeading;
+@property (nonatomic) IBInspectable BOOL showsScale;
@end
diff --git a/platform/ios/src/MGLMapView.h b/platform/ios/src/MGLMapView.h
index 3c5aa2c122..765f0f932b 100644
--- a/platform/ios/src/MGLMapView.h
+++ b/platform/ios/src/MGLMapView.h
@@ -189,13 +189,7 @@ MGL_EXPORT IB_DESIGNABLE
*/
@property (nonatomic, readonly, nullable) MGLStyle *style;
-/**
- URLs of the styles bundled with the library.
-
- @deprecated Call the relevant class method of `MGLStyle` for the URL of a
- particular default style.
- */
-@property (nonatomic, readonly) NS_ARRAY_OF(NSURL *) *bundledStyleURLs __attribute__((deprecated("Call the relevant class method of MGLStyle for the URL of a particular default style.")));
+@property (nonatomic, readonly) NS_ARRAY_OF(NSURL *) *bundledStyleURLs __attribute__((unavailable("Call the relevant class method of MGLStyle for the URL of a particular default style.")));
/**
URL of the style currently displayed in the receiver.
@@ -224,11 +218,20 @@ MGL_EXPORT IB_DESIGNABLE
the server, calling this method does not necessarily ensure that the map view
reflects those changes.
*/
-- (IBAction)reloadStyle:(id)sender;
+- (IBAction)reloadStyle:(nullable id)sender;
+
+/**
+ A Boolean value indicating whether the map may display scale information.
+
+ The scale bar may not be shown at all zoom levels. The view controlled by this
+ property is available at `scaleBar`. The default value of this property is
+ `NO`.
+ */
+@property (nonatomic, assign) BOOL showsScale;
/**
A control indicating the scale of the map. The scale bar is positioned in the
- upper-left corner. The scale bar is hidden by default.
+ upper-left corner. Enable the scale bar via `showsScale`.
*/
@property (nonatomic, readonly) UIView *scaleBar;
@@ -283,17 +286,13 @@ MGL_EXPORT IB_DESIGNABLE
*/
- (IBAction)showAttribution:(id)sender;
-/// :nodoc: Support for style classes has been removed. This property always returns an empty array.
-@property (nonatomic) NS_ARRAY_OF(NSString *) *styleClasses __attribute__((deprecated("This property is non-functional.")));
+@property (nonatomic) NS_ARRAY_OF(NSString *) *styleClasses __attribute__((unavailable("Support for style classes has been removed.")));
-/// :nodoc: Support for style classes has been removed. This property always returns NO.
-- (BOOL)hasStyleClass:(NSString *)styleClass __attribute__((deprecated("This method is non-functional.")));
+- (BOOL)hasStyleClass:(NSString *)styleClass __attribute__((unavailable("Support for style classes has been removed.")));
-/// :nodoc: Support for style classes has been removed. This property is a no-op.
-- (void)addStyleClass:(NSString *)styleClass __attribute__((deprecated("This method is non-functional.")));
+- (void)addStyleClass:(NSString *)styleClass __attribute__((unavailable("Support for style classes has been removed.")));
-/// :nodoc: Support for style classes has been removed. This property is a no-op.
-- (void)removeStyleClass:(NSString *)styleClass __attribute__((deprecated("This method is non-functional.")));
+- (void)removeStyleClass:(NSString *)styleClass __attribute__((unavailable("Support for style classes has been removed.")));
#pragma mark Displaying the User’s Location
@@ -494,6 +493,19 @@ MGL_EXPORT IB_DESIGNABLE
@property(nonatomic, getter=isPitchEnabled) BOOL pitchEnabled;
/**
+ A Boolean value that determines whether the user will receive haptic feedback
+ for certain interactions with the map.
+
+ When this property is set to `YES`, the default, a `UIImpactFeedbackStyleLight`
+ haptic feedback event be played when the user rotates the map to due north
+ (0°).
+
+ This feature requires a device that supports haptic feedback, running iOS 10 or
+ newer.
+ */
+@property(nonatomic, getter=isHapticFeedbackEnabled) BOOL hapticFeedbackEnabled;
+
+/**
A floating-point value that determines the rate of deceleration after the user
lifts their finger.
@@ -669,11 +681,10 @@ MGL_EXPORT IB_DESIGNABLE
want to animate the change, call `-setVisibleCoordinateBounds:animated:`
instead.
- If a longitude is less than −180 degrees or greater than 180 degrees, the visible
- bounds straddles the antimeridian or international date line.
-
- For example, a visible bounds that stretches from Tokyo to San Francisco would have
- coordinates of (35.68476, -220.24257) and (37.78428, -122.41310).
+ If a longitude is less than −180 degrees or greater than 180 degrees, the
+ visible bounds straddles the antimeridian or international date line. For
+ example, if both Tokyo and San Francisco are visible, the visible bounds might
+ extend from (35.68476, −220.24257) to (37.78428, −122.41310).
*/
@property (nonatomic) MGLCoordinateBounds visibleCoordinateBounds;
@@ -681,11 +692,10 @@ MGL_EXPORT IB_DESIGNABLE
Changes the receiver’s viewport to fit the given coordinate bounds,
optionally animating the change.
- To make the visible bounds go across the antimeridian or international date line,
- specify some longitudes less than −180 degrees or greater than 180 degrees.
-
- For example, a visible bounds that stretches from Tokyo to San Francisco would have
- coordinates of (35.68476, -220.24257) and (37.78428, -122.41310).
+ To bring both sides of the antimeridian or international date line into view,
+ specify some longitudes less than −180 degrees or greater than 180 degrees. For
+ example, to show both Tokyo and San Francisco simultaneously, you could set the
+ visible bounds to extend from (35.68476, −220.24257) to (37.78428, −122.41310).
@param bounds The bounds that the viewport will show in its entirety.
@param animated Specify `YES` to animate the change by smoothly scrolling
@@ -696,6 +706,11 @@ MGL_EXPORT IB_DESIGNABLE
/**
Changes the receiver’s viewport to fit the given coordinate bounds and
optionally some additional padding on each side.
+
+ To bring both sides of the antimeridian or international date line into view,
+ specify some longitudes less than −180 degrees or greater than 180 degrees. For
+ example, to show both Tokyo and San Francisco simultaneously, you could set the
+ visible bounds to extend from (35.68476, −220.24257) to (37.78428, −122.41310).
@param bounds The bounds that the viewport will show in its entirety.
@param insets The minimum padding (in screen points) that will be visible
@@ -708,6 +723,11 @@ MGL_EXPORT IB_DESIGNABLE
/**
Changes the receiver’s viewport to fit all of the given coordinates and
optionally some additional padding on each side.
+
+ To bring both sides of the antimeridian or international date line into view,
+ specify some longitudes less than −180 degrees or greater than 180 degrees. For
+ example, to show both Tokyo and San Francisco simultaneously, you could set the
+ visible coordinates to (35.68476, −220.24257) and (37.78428, −122.41310).
@param coordinates The coordinates that the viewport will show.
@param count The number of coordinates. This number must not be greater than
@@ -722,6 +742,11 @@ MGL_EXPORT IB_DESIGNABLE
/**
Changes the receiver’s viewport to fit all of the given coordinates and
optionally some additional padding on each side.
+
+ To bring both sides of the antimeridian or international date line into view,
+ specify some longitudes less than −180 degrees or greater than 180 degrees. For
+ example, to show both Tokyo and San Francisco simultaneously, you could set the
+ visible coordinates to (35.68476, −220.24257) and (37.78428, −122.41310).
@param coordinates The coordinates that the viewport will show.
@param count The number of coordinates. This number must not be greater than
@@ -1004,6 +1029,9 @@ MGL_EXPORT IB_DESIGNABLE
/**
Converts a rectangle in the given view’s coordinate system to a geographic
bounding box.
+
+ If a longitude is less than −180 degrees or greater than 180 degrees, the
+ bounding box straddles the antimeridian or international date line.
@param rect The rectangle to convert.
@param view The view in whose coordinate system the rectangle is expressed.
@@ -1172,17 +1200,32 @@ MGL_EXPORT IB_DESIGNABLE
Assigning a new array to this property selects only the first annotation in
the array.
+
+ If the annotation is of type `MGLPointAnnotation` and is offscreen, the camera
+ will animate to bring the annotation and its callout just on screen. If you
+ need finer control, consider using `-selectAnnotation:animated:`.
+
+ @note In versions prior to `4.0.0` if the annotation was offscreen it was not
+ selected.
*/
@property (nonatomic, copy) NS_ARRAY_OF(id <MGLAnnotation>) *selectedAnnotations;
/**
- Selects an annotation and displays a callout view for it.
+ Selects an annotation and displays its callout view.
- If the given annotation is not visible within the current viewport, this
- method has no effect.
+ The `animated` parameter determines whether the map is panned to bring the
+ annotation on-screen, specifically:
+
+ | `animated` parameter | Effect |
+ |------------------|--------|
+ | `NO` | The annotation is selected, and the callout is presented. However the map is not panned to bring the annotation or callout onscreen. The presentation of the callout is animated. |
+ | `YES` | The annotation is selected, and the callout is presented. If the annotation is offscreen *and* is of type `MGLPointAnnotation`, the map is panned so that the annotation and its callout are brought just onscreen. The annotation is *not* centered within the viewport. |
@param annotation The annotation object to select.
- @param animated If `YES`, the callout view is animated into position.
+ @param animated If `YES`, the annotation and callout view are animated on-screen.
+
+ @note In versions prior to `4.0.0` selecting an offscreen annotation did not
+ change the camera.
*/
- (void)selectAnnotation:(id <MGLAnnotation>)annotation animated:(BOOL)animated;
@@ -1286,9 +1329,9 @@ MGL_EXPORT IB_DESIGNABLE
Each object in the returned array represents a feature rendered by the
current style and provides access to attributes specified by the relevant map
content sources. The returned array includes features loaded by
- `MGLShapeSource` and `MGLVectorSource` objects but does not include anything
- from `MGLRasterSource` objects, or from image, video, or canvas sources, which
- are unsupported by this SDK.
+ `MGLShapeSource` and `MGLVectorTileSource` objects but does not include
+ anything from `MGLRasterTileSource` objects, or from video or canvas sources,
+ which are unsupported by this SDK.
The returned features are drawn by a style layer in the current style. For
example, suppose the current style uses the
@@ -1320,7 +1363,7 @@ MGL_EXPORT IB_DESIGNABLE
Only visible features are returned. To obtain features regardless of
visibility, use the
- `-[MGLVectorSource featuresInSourceLayersWithIdentifiers:predicate:]` and
+ `-[MGLVectorTileSource featuresInSourceLayersWithIdentifiers:predicate:]` and
`-[MGLShapeSource featuresMatchingPredicate:]` methods on the relevant sources.
The returned features may also include features corresponding to annotations.
@@ -1388,9 +1431,9 @@ MGL_EXPORT IB_DESIGNABLE
Each object in the returned array represents a feature rendered by the
current style and provides access to attributes specified by the relevant map
content sources. The returned array includes features loaded by
- `MGLShapeSource` and `MGLVectorSource` objects but does not include anything
- from `MGLRasterSource` objects, or from image, video, or canvas sources, which
- are unsupported by this SDK.
+ `MGLShapeSource` and `MGLVectorTileSource` objects but does not include
+ anything from `MGLRasterTileSource` objects, or from video or canvas sources,
+ which are unsupported by this SDK.
The returned features are drawn by a style layer in the current style. For
example, suppose the current style uses the
@@ -1423,7 +1466,7 @@ MGL_EXPORT IB_DESIGNABLE
Only visible features are returned. To obtain features regardless of
visibility, use the
- `-[MGLVectorSource featuresInSourceLayersWithIdentifiers:predicate:]` and
+ `-[MGLVectorTileSource featuresInSourceLayersWithIdentifiers:predicate:]` and
`-[MGLShapeSource featuresMatchingPredicate:]` methods on the relevant sources.
@note Layer identifiers are not guaranteed to exist across styles or different
@@ -1431,8 +1474,8 @@ MGL_EXPORT IB_DESIGNABLE
style URL to an explicitly versioned style using a convenience method like
`+[MGLStyle outdoorsStyleURLWithVersion:]`, `MGLMapView`’s “Style URL”
inspectable in Interface Builder, or a manually constructed `NSURL`. This
- approach also avoids layer identifer name changes that will occur in the default
- style’s layers over time.
+ approach also avoids layer identifer name changes that will occur in the
+ default style’s layers over time.
@note Layer identifiers are not guaranteed to exist across styles or different
versions of the same style. Applications that use this API must first set
@@ -1462,11 +1505,11 @@ MGL_EXPORT IB_DESIGNABLE
*/
@property (nonatomic) MGLMapDebugMaskOptions debugMask;
-@property (nonatomic, getter=isDebugActive) BOOL debugActive __attribute__((deprecated("Use -debugMask and -setDebugMask:.")));
+@property (nonatomic, getter=isDebugActive) BOOL debugActive __attribute__((unavailable("Use -debugMask and -setDebugMask:.")));
-- (void)toggleDebug __attribute__((deprecated("Use -setDebugMask:.")));
+- (void)toggleDebug __attribute__((unavailable("Use -setDebugMask:.")));
-- (void)emptyMemoryCache __attribute__((deprecated));
+- (void)emptyMemoryCache __attribute__((unavailable));
@end
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index 6be6a71f66..b7d0974872 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -41,7 +41,7 @@
#import "MGLGeometry_Private.h"
#import "MGLMultiPoint_Private.h"
#import "MGLOfflineStorage_Private.h"
-#import "MGLVectorSource_Private.h"
+#import "MGLVectorTileSource_Private.h"
#import "MGLFoundation_Private.h"
#import "MGLRendererFrontend.h"
#import "MGLRendererConfiguration.h"
@@ -66,6 +66,7 @@
#import "MGLStyle_Private.h"
#import "MGLStyleLayer_Private.h"
#import "MGLMapboxEvents.h"
+#import "MMEConstants.h"
#import "MGLSDKUpdateChecker.h"
#import "MGLCompactCalloutView.h"
#import "MGLAnnotationContainerView.h"
@@ -143,6 +144,9 @@ const CGFloat MGLAnnotationImagePaddingForCallout = 1;
const CGSize MGLAnnotationAccessibilityElementMinimumSize = CGSizeMake(10, 10);
+/// Padding to edge of view that an offscreen annotation must have when being brought onscreen (by being selected)
+const UIEdgeInsets MGLMapViewOffscreenAnnotationPadding = UIEdgeInsetsMake(-20.0f, -20.0f, -20.0f, -20.0f);
+
/// An indication that the requested annotation was not found or is nonexistent.
enum { MGLAnnotationTagNotFound = UINT32_MAX };
@@ -227,6 +231,7 @@ public:
@property (nonatomic) CGFloat quickZoomStart;
@property (nonatomic, getter=isDormant) BOOL dormant;
@property (nonatomic, readonly, getter=isRotationAllowed) BOOL rotationAllowed;
+@property (nonatomic) BOOL shouldTriggerHapticFeedbackForCompass;
@property (nonatomic) MGLMapViewProxyAccessibilityElement *mapViewProxyAccessibilityElement;
@property (nonatomic) MGLAnnotationContainerView *annotationContainerView;
@property (nonatomic) MGLUserLocation *userLocation;
@@ -244,8 +249,6 @@ public:
BOOL _opaque;
- NS_MUTABLE_ARRAY_OF(NSURL *) *_bundledStyleURLs;
-
MGLAnnotationTagContextMap _annotationContextsByAnnotationTag;
MGLAnnotationObjectTagMap _annotationTagsByAnnotation;
@@ -270,7 +273,7 @@ public:
CADisplayLink *_displayLink;
BOOL _needsDisplayRefresh;
- NSUInteger _changeDelimiterSuppressionDepth;
+ NSInteger _changeDelimiterSuppressionDepth;
/// Center coordinate of the pinch gesture on the previous iteration of the gesture.
CLLocationCoordinate2D _previousPinchCenterCoordinate;
@@ -524,6 +527,8 @@ public:
[_twoFingerTap requireGestureRecognizerToFail:_twoFingerDrag];
[self addGestureRecognizer:_twoFingerTap];
+ _hapticFeedbackEnabled = YES;
+
_decelerationRate = MGLMapViewDecelerationRateNormal;
_quickZoom = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleQuickZoomGesture:)];
@@ -568,7 +573,8 @@ public:
_targetCoordinate = kCLLocationCoordinate2DInvalid;
if ([UIApplication sharedApplication].applicationState != UIApplicationStateBackground) {
- [MGLMapboxEvents pushEvent:MGLEventTypeMapLoad withAttributes:@{}];
+ [MGLMapboxEvents pushTurnstileEvent];
+ [MGLMapboxEvents pushEvent:MMEEventTypeMapLoad withAttributes:@{}];
}
}
@@ -970,8 +976,8 @@ public:
- (void)layoutSubviews
{
// Calling this here instead of in the scale bar itself because if this is done in the
- // scale bar instance, it triggers a call to this this `layoutSubviews` method that
- // calls `_mbglMap->setSize()` just below that triggers rendering update which triggers
+ // scale bar instance, it triggers a call to this `layoutSubviews` method that calls
+ // `_mbglMap->setSize()` just below that triggers rendering update which triggers
// another scale bar update which causes a rendering update loop and a major performace
// degradation. The only time the scale bar's intrinsic content size _must_ invalidated
// is here as a reaction to this object's view dimension changes.
@@ -1220,7 +1226,8 @@ public:
[self validateLocationServices];
- [MGLMapboxEvents pushEvent:MGLEventTypeMapLoad withAttributes:@{}];
+ [MGLMapboxEvents pushTurnstileEvent];
+ [MGLMapboxEvents pushEvent:MMEEventTypeMapLoad withAttributes:@{}];
}
}
@@ -1332,7 +1339,7 @@ public:
if (pan.state == UIGestureRecognizerStateBegan)
{
- [self trackGestureEvent:MGLEventGesturePanStart forRecognizer:pan];
+ [self trackGestureEvent:MMEEventGesturePanStart forRecognizer:pan];
self.userTrackingMode = MGLUserTrackingModeNone;
@@ -1380,10 +1387,10 @@ public:
CLLocationCoordinate2D panCoordinate = [self convertPoint:pointInView toCoordinateFromView:pan.view];
int zoom = round([self zoomLevel]);
- [MGLMapboxEvents pushEvent:MGLEventTypeMapDragEnd withAttributes:@{
- MGLEventKeyLatitude: @(panCoordinate.latitude),
- MGLEventKeyLongitude: @(panCoordinate.longitude),
- MGLEventKeyZoomLevel: @(zoom)
+ [MGLMapboxEvents pushEvent:MMEEventTypeMapDragEnd withAttributes:@{
+ MMEEventKeyLatitude: @(panCoordinate.latitude),
+ MMEEventKeyLongitude: @(panCoordinate.longitude),
+ MMEEventKeyZoomLevel: @(zoom)
}];
}
@@ -1402,7 +1409,7 @@ public:
if (pinch.state == UIGestureRecognizerStateBegan)
{
- [self trackGestureEvent:MGLEventGesturePinchStart forRecognizer:pinch];
+ [self trackGestureEvent:MMEEventGesturePinchStart forRecognizer:pinch];
self.scale = powf(2, _mbglMap->getZoom());
@@ -1503,7 +1510,7 @@ public:
if (rotate.state == UIGestureRecognizerStateBegan)
{
- [self trackGestureEvent:MGLEventGestureRotateStart forRecognizer:rotate];
+ [self trackGestureEvent:MMEEventGestureRotateStart forRecognizer:rotate];
self.angle = MGLRadiansFromDegrees(_mbglMap->getBearing()) * -1;
@@ -1512,6 +1519,8 @@ public:
self.userTrackingMode = MGLUserTrackingModeFollow;
}
+ self.shouldTriggerHapticFeedbackForCompass = NO;
+
[self notifyGestureDidBegin];
}
else if (rotate.state == UIGestureRecognizerStateChanged)
@@ -1534,6 +1543,22 @@ public:
}
[self cameraIsChanging];
+
+ // Trigger a light haptic feedback event when the user rotates to due north.
+ if (@available(iOS 10.0, *))
+ {
+ if (self.isHapticFeedbackEnabled && fabs(newDegrees) <= 1 && self.shouldTriggerHapticFeedbackForCompass)
+ {
+ UIImpactFeedbackGenerator *hapticFeedback = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleLight];
+ [hapticFeedback impactOccurred];
+
+ self.shouldTriggerHapticFeedbackForCompass = NO;
+ }
+ else if (fabs(newDegrees) > 1)
+ {
+ self.shouldTriggerHapticFeedbackForCompass = YES;
+ }
+ }
}
else if (rotate.state == UIGestureRecognizerStateEnded || rotate.state == UIGestureRecognizerStateCancelled)
{
@@ -1575,7 +1600,7 @@ public:
{
return;
}
- [self trackGestureEvent:MGLEventGestureSingleTap forRecognizer:singleTap];
+ [self trackGestureEvent:MMEEventGestureSingleTap forRecognizer:singleTap];
if (self.mapViewProxyAccessibilityElement.accessibilityElementIsFocused)
{
@@ -1601,7 +1626,7 @@ public:
{
CGPoint calloutPoint = [singleTap locationInView:self];
CGRect positionRect = [self positioningRectForAnnotation:annotation defaultCalloutPoint:calloutPoint];
- [self selectAnnotation:annotation animated:YES calloutPositioningRect:positionRect];
+ [self selectAnnotation:annotation moveOnscreen:YES animateSelection:YES calloutPositioningRect:positionRect];
}
else if (self.selectedAnnotation)
{
@@ -1697,7 +1722,7 @@ public:
if ([self _shouldChangeFromCamera:oldCamera toCamera:toCamera])
{
- [self trackGestureEvent:MGLEventGestureDoubleTap forRecognizer:doubleTap];
+ [self trackGestureEvent:MMEEventGestureDoubleTap forRecognizer:doubleTap];
mbgl::ScreenCoordinate center(gesturePoint.x, gesturePoint.y);
_mbglMap->setZoom(newZoom, center, MGLDurationFromTimeInterval(MGLAnimationDuration));
@@ -1728,7 +1753,7 @@ public:
if (twoFingerTap.state == UIGestureRecognizerStateBegan)
{
- [self trackGestureEvent:MGLEventGestureTwoFingerSingleTap forRecognizer:twoFingerTap];
+ [self trackGestureEvent:MMEEventGestureTwoFingerSingleTap forRecognizer:twoFingerTap];
[self notifyGestureDidBegin];
}
@@ -1767,7 +1792,7 @@ public:
if (quickZoom.state == UIGestureRecognizerStateBegan)
{
- [self trackGestureEvent:MGLEventGestureQuickZoom forRecognizer:quickZoom];
+ [self trackGestureEvent:MMEEventGestureQuickZoom forRecognizer:quickZoom];
self.scale = powf(2, _mbglMap->getZoom());
@@ -1812,7 +1837,7 @@ public:
if (twoFingerDrag.state == UIGestureRecognizerStateBegan)
{
- [self trackGestureEvent:MGLEventGesturePitchStart forRecognizer:twoFingerDrag];
+ [self trackGestureEvent:MMEEventGesturePitchStart forRecognizer:twoFingerDrag];
[self notifyGestureDidBegin];
}
@@ -2017,11 +2042,11 @@ public:
CLLocationCoordinate2D gestureCoordinate = [self convertPoint:pointInView toCoordinateFromView:recognizer.view];
int zoom = round([self zoomLevel]);
- [MGLMapboxEvents pushEvent:MGLEventTypeMapTap withAttributes:@{
- MGLEventKeyLatitude: @(gestureCoordinate.latitude),
- MGLEventKeyLongitude: @(gestureCoordinate.longitude),
- MGLEventKeyZoomLevel: @(zoom),
- MGLEventKeyGestureID: gestureID
+ [MGLMapboxEvents pushEvent:MMEEventTypeMapTap withAttributes:@{
+ MMEEventKeyLatitude: @(gestureCoordinate.latitude),
+ MMEEventKeyLongitude: @(gestureCoordinate.longitude),
+ MMEEventKeyZoomLevel: @(zoom),
+ MMEEventKeyGestureID: gestureID
}];
}
@@ -2293,16 +2318,6 @@ public:
MGLMapDebugCollisionBoxesMask) : 0;
}
-- (BOOL)isDebugActive
-{
- return self.debugMask;
-}
-
-- (void)toggleDebug
-{
- self.debugActive = !self.debugActive;
-}
-
- (void)resetNorth
{
[self resetNorthAnimated:YES];
@@ -2325,11 +2340,6 @@ public:
heading:heading];
}
-- (void)emptyMemoryCache
-{
- _rendererFrontend->reduceMemoryUse();
-}
-
- (void)setZoomEnabled:(BOOL)zoomEnabled
{
_zoomEnabled = zoomEnabled;
@@ -2357,6 +2367,17 @@ public:
self.twoFingerDrag.enabled = pitchEnabled;
}
+- (void)setShowsScale:(BOOL)showsScale
+{
+ _showsScale = showsScale;
+ self.scaleBar.hidden = !showsScale;
+
+ if (showsScale)
+ {
+ [self updateScaleBar];
+ }
+}
+
#pragma mark - Accessibility -
- (NSString *)accessibilityValue
@@ -3439,36 +3460,24 @@ public:
/// bounding box.
- (mbgl::LatLngBounds)convertRect:(CGRect)rect toLatLngBoundsFromView:(nullable UIView *)view
{
- mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty();
- bounds.extend([self convertPoint:rect.origin toLatLngFromView:view]);
- bounds.extend([self convertPoint:{ CGRectGetMaxX(rect), CGRectGetMinY(rect) } toLatLngFromView:view]);
- bounds.extend([self convertPoint:{ CGRectGetMaxX(rect), CGRectGetMaxY(rect) } toLatLngFromView:view]);
- bounds.extend([self convertPoint:{ CGRectGetMinX(rect), CGRectGetMaxY(rect) } toLatLngFromView:view]);
-
- // The world is wrapping if a point just outside the bounds is also within
- // the rect.
- mbgl::LatLng outsideLatLng;
- if (bounds.west() > -180)
- {
- outsideLatLng = {
- (bounds.south() + bounds.north()) / 2,
- bounds.west() - 1,
- };
- }
- else if (bounds.east() < 180)
- {
- outsideLatLng = {
- (bounds.south() + bounds.north()) / 2,
- bounds.east() + 1,
- };
- }
-
- // If the world is wrapping, extend the bounds to cover all longitudes.
- if (CGRectContainsPoint(rect, [self convertLatLng:outsideLatLng toPointToView:view]))
- {
- bounds.extend(mbgl::LatLng(bounds.south(), -180));
- bounds.extend(mbgl::LatLng(bounds.south(), 180));
- }
+ auto bounds = mbgl::LatLngBounds::empty();
+ auto topLeft = [self convertPoint:{ CGRectGetMinX(rect), CGRectGetMinY(rect) } toLatLngFromView:view];
+ auto topRight = [self convertPoint:{ CGRectGetMaxX(rect), CGRectGetMinY(rect) } toLatLngFromView:view];
+ auto bottomRight = [self convertPoint:{ CGRectGetMaxX(rect), CGRectGetMaxY(rect) } toLatLngFromView:view];
+ auto bottomLeft = [self convertPoint:{ CGRectGetMinX(rect), CGRectGetMaxY(rect) } toLatLngFromView:view];
+
+ // If the bounds straddles the antimeridian, unwrap it so that one side
+ // extends beyond ±180° longitude.
+ auto center = [self convertPoint:{ CGRectGetMidX(rect), CGRectGetMidY(rect) } toLatLngFromView:view];
+ topLeft.unwrapForShortestPath(center);
+ topRight.unwrapForShortestPath(center);
+ bottomRight.unwrapForShortestPath(center);
+ bottomLeft.unwrapForShortestPath(center);
+
+ bounds.extend(topLeft);
+ bounds.extend(topRight);
+ bounds.extend(bottomRight);
+ bounds.extend(bottomLeft);
return bounds;
}
@@ -3478,11 +3487,6 @@ public:
return mbgl::Projection::getMetersPerPixelAtLatitude(latitude, self.zoomLevel);
}
-- (CLLocationDistance)metersPerPixelAtLatitude:(CLLocationDegrees)latitude
-{
- return [self metersPerPointAtLatitude:latitude];
-}
-
#pragma mark - Camera Change Reason -
- (void)resetCameraChangeReason
@@ -3490,70 +3494,6 @@ public:
self.cameraChangeReasonBitmask = MGLCameraChangeReasonNone;
}
-#pragma mark - Styling -
-
-- (NS_ARRAY_OF(NSURL *) *)bundledStyleURLs
-{
- if ( ! _bundledStyleURLs)
- {
- _bundledStyleURLs = [NSMutableArray array];
- for (NSUInteger i = 0; i < mbgl::util::default_styles::numOrderedStyles; i++)
- {
- NSURL *styleURL = [NSURL URLWithString:@(mbgl::util::default_styles::orderedStyles[i].url)];
- [_bundledStyleURLs addObject:styleURL];
- }
- }
-
- return [NSArray arrayWithArray:_bundledStyleURLs];
-}
-
-- (nullable NSString *)styleID
-{
- [NSException raise:@"Method unavailable" format:
- @"%s has been replaced by -[MGLMapView styleURL].",
- __PRETTY_FUNCTION__];
- return nil;
-}
-
-- (void)setStyleID:(nullable NSString *)styleID
-{
- [NSException raise:@"Method unavailable" format:
- @"%s has been replaced by -[MGLMapView setStyleURL:].\n\n"
- @"If you previously set this style ID in a storyboard inspectable, select the MGLMapView in Interface Builder and delete the “styleID” entry from the User Defined Runtime Attributes section of the Identity inspector. "
- @"Then go to the Attributes inspector and enter “mapbox://styles/%@” into the “Style URL” field.",
- __PRETTY_FUNCTION__, styleID];
-}
-
-- (NS_ARRAY_OF(NSString *) *)styleClasses
-{
- return [self.style styleClasses];
-}
-
-- (void)setStyleClasses:(NS_ARRAY_OF(NSString *) *)appliedClasses
-{
- [self setStyleClasses:appliedClasses transitionDuration:0];
-}
-
-- (void)setStyleClasses:(NS_ARRAY_OF(NSString *) *)appliedClasses transitionDuration:(NSTimeInterval)transitionDuration
-{
- [self.style setStyleClasses:appliedClasses transitionDuration:transitionDuration];
-}
-
-- (BOOL)hasStyleClass:(NSString *)styleClass
-{
- return [self.style hasStyleClass:styleClass];
-}
-
-- (void)addStyleClass:(NSString *)styleClass
-{
- [self.style addStyleClass:styleClass];
-}
-
-- (void)removeStyleClass:(NSString *)styleClass
-{
- [self.style removeStyleClass:styleClass];
-}
-
#pragma mark - Annotations -
- (nullable NS_ARRAY_OF(id <MGLAnnotation>) *)annotations
@@ -4174,51 +4114,48 @@ public:
MGLAnnotationTag hitAnnotationTag = MGLAnnotationTagNotFound;
if (nearbyAnnotations.size())
{
- // The annotation tags need to be stable in order to compare them with
- // the remembered tags.
- std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end());
-
+ // The first selection in the cycle should be the one nearest to the
+ // tap. Also the annotation tags need to be stable in order to compare them with
+ // the remembered tags _annotationsNearbyLastTap.
+ CLLocationCoordinate2D currentCoordinate = [self convertPoint:point toCoordinateFromView:self];
+ std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag tagA, const MGLAnnotationTag tagB) {
+ CLLocationCoordinate2D coordinateA = [[self annotationWithTag:tagA] coordinate];
+ CLLocationCoordinate2D coordinateB = [[self annotationWithTag:tagB] coordinate];
+ CLLocationDegrees deltaA = hypot(coordinateA.latitude - currentCoordinate.latitude,
+ coordinateA.longitude - currentCoordinate.longitude);
+ CLLocationDegrees deltaB = hypot(coordinateB.latitude - currentCoordinate.latitude,
+ coordinateB.longitude - currentCoordinate.longitude);
+ return deltaA < deltaB;
+ });
+
if (nearbyAnnotations == _annotationsNearbyLastTap)
{
- // The first selection in the cycle should be the one nearest to the
- // tap.
- CLLocationCoordinate2D currentCoordinate = [self convertPoint:point toCoordinateFromView:self];
- std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag tagA, const MGLAnnotationTag tagB) {
- CLLocationCoordinate2D coordinateA = [[self annotationWithTag:tagA] coordinate];
- CLLocationCoordinate2D coordinateB = [[self annotationWithTag:tagB] coordinate];
- CLLocationDegrees deltaA = hypot(coordinateA.latitude - currentCoordinate.latitude,
- coordinateA.longitude - currentCoordinate.longitude);
- CLLocationDegrees deltaB = hypot(coordinateB.latitude - currentCoordinate.latitude,
- coordinateB.longitude - currentCoordinate.longitude);
- return deltaA < deltaB;
- });
-
// The last time we persisted a set of annotations, we had the same
// set of annotations as we do now. Cycle through them.
if (_selectedAnnotationTag == MGLAnnotationTagNotFound
- || _selectedAnnotationTag == _annotationsNearbyLastTap.back())
+ || _selectedAnnotationTag == nearbyAnnotations.back())
{
// Either no annotation is selected or the last annotation in
// the set was selected. Wrap around to the first annotation in
// the set.
- hitAnnotationTag = _annotationsNearbyLastTap.front();
+ hitAnnotationTag = nearbyAnnotations.front();
}
else
{
- auto result = std::find(_annotationsNearbyLastTap.begin(),
- _annotationsNearbyLastTap.end(),
+ auto result = std::find(nearbyAnnotations.begin(),
+ nearbyAnnotations.end(),
_selectedAnnotationTag);
- if (result == _annotationsNearbyLastTap.end())
+ if (result == nearbyAnnotations.end())
{
// An annotation from this set hasn’t been selected before.
// Select the first (nearest) one.
- hitAnnotationTag = _annotationsNearbyLastTap.front();
+ hitAnnotationTag = nearbyAnnotations.front();
}
else
{
// Step to the next annotation in the set.
- auto distance = std::distance(_annotationsNearbyLastTap.begin(), result);
- hitAnnotationTag = _annotationsNearbyLastTap[distance + 1];
+ auto distance = std::distance(nearbyAnnotations.begin(), result);
+ hitAnnotationTag = nearbyAnnotations[distance + 1];
}
}
}
@@ -4230,7 +4167,7 @@ public:
{
_annotationsNearbyLastTap = nearbyAnnotations;
}
-
+
// Choose the first nearby annotation.
if (nearbyAnnotations.size())
{
@@ -4259,6 +4196,12 @@ public:
});
}
+
+- (BOOL)isBringingAnnotationOnscreenSupportedForAnnotation:(id<MGLAnnotation>)annotation animated:(BOOL)animated {
+ // Consider delegating
+ return animated && [annotation isKindOfClass:[MGLPointAnnotation class]];
+}
+
- (id <MGLAnnotation>)selectedAnnotation
{
if (_userLocationAnnotationIsSelected)
@@ -4299,20 +4242,16 @@ public:
if ([firstAnnotation isKindOfClass:[MGLMultiPoint class]]) return;
- // Select the annotation if it’s visible.
- if (MGLCoordinateInCoordinateBounds(firstAnnotation.coordinate, self.visibleCoordinateBounds))
- {
- [self selectAnnotation:firstAnnotation animated:NO];
- }
+ [self selectAnnotation:firstAnnotation animated:YES];
}
- (void)selectAnnotation:(id <MGLAnnotation>)annotation animated:(BOOL)animated
{
CGRect positioningRect = [self positioningRectForAnnotation:annotation defaultCalloutPoint:CGPointZero];
- [self selectAnnotation:annotation animated:animated calloutPositioningRect:positioningRect];
+ [self selectAnnotation:annotation moveOnscreen:animated animateSelection:YES calloutPositioningRect:positioningRect];
}
-- (void)selectAnnotation:(id <MGLAnnotation>)annotation animated:(BOOL)animated calloutPositioningRect:(CGRect)calloutPositioningRect
+- (void)selectAnnotation:(id <MGLAnnotation>)annotation moveOnscreen:(BOOL)moveOnscreen animateSelection:(BOOL)animateSelection calloutPositioningRect:(CGRect)calloutPositioningRect
{
if ( ! annotation) return;
@@ -4336,22 +4275,34 @@ public:
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
annotationView = annotationContext.annotationView;
if (annotationView && annotationView.enabled) {
- // Annotations represented by views use the view frame as the positioning rect.
- calloutPositioningRect = annotationView.frame;
- [annotationView.superview bringSubviewToFront:annotationView];
- [annotationView setSelected:YES animated:animated];
+ // Annotations represented by views use the view frame as the positioning rect.
+ calloutPositioningRect = annotationView.frame;
+ [annotationView.superview bringSubviewToFront:annotationView];
+
+ [annotationView setSelected:YES animated:animateSelection];
}
}
self.selectedAnnotation = annotation;
+ // Determine if we're allowed to move this offscreen annotation on screen, even though we've asked it to
+ if (moveOnscreen) {
+ moveOnscreen = [self isBringingAnnotationOnscreenSupportedForAnnotation:annotation animated:animateSelection];
+ }
+
+ CGRect expandedPositioningRect = UIEdgeInsetsInsetRect(calloutPositioningRect, MGLMapViewOffscreenAnnotationPadding);
+
+ // Used for callout positioning, and moving offscreen annotations onscreen.
+ CGRect constrainedRect = UIEdgeInsetsInsetRect(self.bounds, self.contentInset);
+
+ UIView <MGLCalloutView> *calloutView = nil;
+
if ([annotation respondsToSelector:@selector(title)] &&
annotation.title &&
[self.delegate respondsToSelector:@selector(mapView:annotationCanShowCallout:)] &&
[self.delegate mapView:self annotationCanShowCallout:annotation])
{
// build the callout
- UIView <MGLCalloutView> *calloutView;
if ([self.delegate respondsToSelector:@selector(mapView:calloutViewForAnnotation:)])
{
id providedCalloutView = [self.delegate mapView:self calloutViewForAnnotation:annotation];
@@ -4409,13 +4360,51 @@ public:
// set annotation delegate to handle taps on the callout view
calloutView.delegate = self;
- // present popup
- [calloutView presentCalloutFromRect:calloutPositioningRect
- inView:self.glView
- constrainedToView:self.glView
- animated:animated];
+ // If the callout view provides inset (outset) information, we can use it to expand our positioning
+ // rect, which we then use to help move the annotation on-screen if want need to.
+ if (moveOnscreen && [calloutView respondsToSelector:@selector(marginInsetsHintForPresentationFromRect:)]) {
+ UIEdgeInsets margins = [calloutView marginInsetsHintForPresentationFromRect:calloutPositioningRect];
+ expandedPositioningRect = UIEdgeInsetsInsetRect(expandedPositioningRect, margins);
+ }
+ }
+
+ if (moveOnscreen)
+ {
+ moveOnscreen = NO;
+
+ // Need to consider the content insets.
+ CGRect bounds = UIEdgeInsetsInsetRect(self.bounds, self.contentInset);
+
+ // Any one of these cases should trigger a move onscreen
+ if (CGRectGetMinX(calloutPositioningRect) < CGRectGetMinX(bounds))
+ {
+ constrainedRect.origin.x = expandedPositioningRect.origin.x;
+ moveOnscreen = YES;
+ }
+ else if (CGRectGetMaxX(calloutPositioningRect) > CGRectGetMaxX(bounds))
+ {
+ constrainedRect.origin.x = CGRectGetMaxX(expandedPositioningRect) - constrainedRect.size.width;
+ moveOnscreen = YES;
+ }
+
+ if (CGRectGetMinY(calloutPositioningRect) < CGRectGetMinY(bounds))
+ {
+ constrainedRect.origin.y = expandedPositioningRect.origin.y;
+ moveOnscreen = YES;
+ }
+ else if (CGRectGetMaxY(calloutPositioningRect) > CGRectGetMaxY(bounds))
+ {
+ constrainedRect.origin.y = CGRectGetMaxY(expandedPositioningRect) - constrainedRect.size.height;
+ moveOnscreen = YES;
+ }
}
+ // Remember, calloutView can be nil here.
+ [calloutView presentCalloutFromRect:calloutPositioningRect
+ inView:self.glView
+ constrainedToRect:constrainedRect
+ animated:animateSelection];
+
// notify delegate
if ([self.delegate respondsToSelector:@selector(mapView:didSelectAnnotation:)])
{
@@ -4426,6 +4415,13 @@ public:
{
[self.delegate mapView:self didSelectAnnotationView:annotationView];
}
+
+ if (moveOnscreen)
+ {
+ CGPoint center = CGPointMake(CGRectGetMidX(constrainedRect), CGRectGetMidY(constrainedRect));
+ CLLocationCoordinate2D centerCoord = [self convertPoint:center toCoordinateFromView:self];
+ [self setCenterCoordinate:centerCoord animated:animateSelection];
+ }
}
- (MGLCompactCalloutView *)calloutViewForAnnotation:(id <MGLAnnotation>)annotation
@@ -4616,6 +4612,7 @@ public:
animated:animated];
}
+
#pragma mark Annotation Image Delegate
- (void)annotationImageNeedsRedisplay:(MGLAnnotationImage *)annotationImage
@@ -4625,11 +4622,6 @@ public:
NSString *fallbackReuseIdentifier = MGLDefaultStyleMarkerSymbolName;
NSString *fallbackIconIdentifier = [MGLAnnotationSpritePrefix stringByAppendingString:fallbackReuseIdentifier];
- // Remove the old icon from the style.
- if ( ! [iconIdentifier isEqualToString:fallbackIconIdentifier]) {
- _mbglMap->removeAnnotationImage(iconIdentifier.UTF8String);
- }
-
if (annotationImage.image)
{
// Add the new icon to the style.
@@ -4746,12 +4738,8 @@ public:
userLocationAnnotationView = (MGLUserLocationAnnotationView *)[self.delegate mapView:self viewForAnnotation:self.userLocation];
if (userLocationAnnotationView && ! [userLocationAnnotationView isKindOfClass:MGLUserLocationAnnotationView.class])
{
- static dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- NSLog(@"Ignoring user location annotation view with type %@. User location annotation view must be a kind of MGLUserLocationAnnotationView. This warning is only shown once and will become an error in a future version.", NSStringFromClass(userLocationAnnotationView.class));
- });
-
- userLocationAnnotationView = nil;
+ [NSException raise:@"MGLUserLocationAnnotationTypeException"
+ format:@"User location annotation view must be a kind of MGLUserLocationAnnotationView. %@", userLocationAnnotationView.debugDescription];
}
}
@@ -5455,10 +5443,7 @@ public:
}
[self updateCompass];
-
- if (!self.scaleBar.hidden) {
- [(MGLScaleBar *)self.scaleBar setMetersPerPoint:[self metersPerPointAtLatitude:self.centerCoordinate.latitude]];
- }
+ [self updateScaleBar];
if ([self.delegate respondsToSelector:@selector(mapView:regionIsChangingWithReason:)])
{
@@ -5476,6 +5461,7 @@ public:
}
[self updateCompass];
+ [self updateScaleBar];
if ( ! [self isSuppressingChangeDelimiters])
{
@@ -5920,6 +5906,17 @@ public:
}
}
+- (void)updateScaleBar
+{
+ // Use the `hidden` property (instead of `self.showsScale`) so that we don't
+ // break developers who still rely on the <4.0.0 approach of directly
+ // setting this property.
+ if ( ! self.scaleBar.hidden)
+ {
+ [(MGLScaleBar *)self.scaleBar setMetersPerPoint:[self metersPerPointAtLatitude:self.centerCoordinate.latitude]];
+ }
+}
+
+ (UIImage *)resourceImageNamed:(NSString *)imageName
{
UIImage *image = [UIImage imageNamed:imageName
diff --git a/platform/ios/src/MGLMapboxEvents.h b/platform/ios/src/MGLMapboxEvents.h
index 98f59ffd3f..cbac578798 100644
--- a/platform/ios/src/MGLMapboxEvents.h
+++ b/platform/ios/src/MGLMapboxEvents.h
@@ -1,44 +1,17 @@
#import <Foundation/Foundation.h>
-
-#import "MGLTypes.h"
+#import "MMEEventsManager.h"
NS_ASSUME_NONNULL_BEGIN
-// Event types
-extern NSString *const MGLEventTypeAppUserTurnstile;
-extern NSString *const MGLEventTypeMapLoad;
-extern NSString *const MGLEventTypeMapTap;
-extern NSString *const MGLEventTypeMapDragEnd;
-extern NSString *const MGLEventTypeLocation;
-
-// Event keys
-extern NSString *const MGLEventKeyLatitude;
-extern NSString *const MGLEventKeyLongitude;
-extern NSString *const MGLEventKeyZoomLevel;
-extern NSString *const MGLEventKeyGestureID;
-
-// Gestures
-extern NSString *const MGLEventGestureSingleTap;
-extern NSString *const MGLEventGestureDoubleTap;
-extern NSString *const MGLEventGestureTwoFingerSingleTap;
-extern NSString *const MGLEventGestureQuickZoom;
-extern NSString *const MGLEventGesturePanStart;
-extern NSString *const MGLEventGesturePinchStart;
-extern NSString *const MGLEventGestureRotateStart;
-extern NSString *const MGLEventGesturePitchStart;
-
-typedef NS_DICTIONARY_OF(NSString *, id) MGLMapboxEventAttributes;
-typedef NS_MUTABLE_DICTIONARY_OF(NSString *, id) MGLMutableMapboxEventAttributes;
-
@interface MGLMapboxEvents : NSObject
-+ (nullable instancetype)sharedManager;
++ (nullable instancetype)sharedInstance;
-// You must call these methods from the main thread.
-//
-+ (void)pushEvent:(NSString *)event withAttributes:(MGLMapboxEventAttributes *)attributeDictionary;
-+ (void)ensureMetricsOptoutExists;
++ (void)setupWithAccessToken:(NSString *)accessToken;
++ (void)pushTurnstileEvent;
++ (void)pushEvent:(NSString *)event withAttributes:(MMEMapboxEventAttributes *)attributeDictionary;
+ (void)flush;
++ (void)ensureMetricsOptoutExists;
@end
diff --git a/platform/ios/src/MGLMapboxEvents.m b/platform/ios/src/MGLMapboxEvents.m
index 273af5b3bc..05f291d8a0 100644
--- a/platform/ios/src/MGLMapboxEvents.m
+++ b/platform/ios/src/MGLMapboxEvents.m
@@ -1,646 +1,166 @@
#import "MGLMapboxEvents.h"
-#import <UIKit/UIKit.h>
-#import <CoreLocation/CoreLocation.h>
-#import "MGLAccountManager.h"
+#import "NSBundle+MGLAdditions.h"
#import "NSProcessInfo+MGLAdditions.h"
-#import "NSException+MGLAdditions.h"
-#import "MGLAPIClient.h"
-#import "MGLLocationManager.h"
-#import "MGLTelemetryConfig.h"
-#include <mbgl/storage/reachability.h>
-#include <sys/sysctl.h>
+static NSString * const MGLAPIClientUserAgentBase = @"mapbox-maps-ios";
+static NSString * const MGLMapboxAccountType = @"MGLMapboxAccountType";
+static NSString * const MGLMapboxMetricsEnabled = @"MGLMapboxMetricsEnabled";
+static NSString * const MGLMapboxMetricsDebugLoggingEnabled = @"MGLMapboxMetricsDebugLoggingEnabled";
+static NSString * const MGLTelemetryAccessToken = @"MGLTelemetryAccessToken";
+static NSString * const MGLTelemetryBaseURL = @"MGLTelemetryBaseURL";
-// Event types
-NSString *const MGLEventTypeAppUserTurnstile = @"appUserTurnstile";
-NSString *const MGLEventTypeMapLoad = @"map.load";
-NSString *const MGLEventTypeMapTap = @"map.click";
-NSString *const MGLEventTypeMapDragEnd = @"map.dragend";
-NSString *const MGLEventTypeLocation = @"location";
-NSString *const MGLEventTypeLocalDebug = @"debug";
+@interface MGLMapboxEvents ()
-// Gestures
-NSString *const MGLEventGestureSingleTap = @"SingleTap";
-NSString *const MGLEventGestureDoubleTap = @"DoubleTap";
-NSString *const MGLEventGestureTwoFingerSingleTap = @"TwoFingerTap";
-NSString *const MGLEventGestureQuickZoom = @"QuickZoom";
-NSString *const MGLEventGesturePanStart = @"Pan";
-NSString *const MGLEventGesturePinchStart = @"Pinch";
-NSString *const MGLEventGestureRotateStart = @"Rotation";
-NSString *const MGLEventGesturePitchStart = @"Pitch";
-
-// Event keys
-NSString *const MGLEventKeyLatitude = @"lat";
-NSString *const MGLEventKeyLongitude = @"lng";
-NSString *const MGLEventKeyZoomLevel = @"zoom";
-NSString *const MGLEventKeySpeed = @"speed";
-NSString *const MGLEventKeyCourse = @"course";
-NSString *const MGLEventKeyGestureID = @"gesture";
-NSString *const MGLEventHorizontalAccuracy = @"horizontalAccuracy";
-NSString *const MGLEventKeyLocalDebugDescription = @"debug.description";
-
-static NSString *const MGLEventKeyEvent = @"event";
-static NSString *const MGLEventKeyCreated = @"created";
-static NSString *const MGLEventKeyVendorID = @"userId";
-static NSString *const MGLEventKeyModel = @"model";
-static NSString *const MGLEventKeyEnabledTelemetry = @"enabled.telemetry";
-static NSString *const MGLEventKeyOperatingSystem = @"operatingSystem";
-static NSString *const MGLEventKeyResolution = @"resolution";
-static NSString *const MGLEventKeyAccessibilityFontScale = @"accessibilityFontScale";
-static NSString *const MGLEventKeyOrientation = @"orientation";
-static NSString *const MGLEventKeyPluggedIn = @"pluggedIn";
-static NSString *const MGLEventKeyWifi = @"wifi";
-static NSString *const MGLEventKeySource = @"source";
-static NSString *const MGLEventKeySessionId = @"sessionId";
-static NSString *const MGLEventKeyApplicationState = @"applicationState";
-static NSString *const MGLEventKeyAltitude = @"altitude";
-
-static NSString *const MGLMapboxAccountType = @"MGLMapboxAccountType";
-static NSString *const MGLMapboxMetricsEnabled = @"MGLMapboxMetricsEnabled";
-
-// SDK event source
-static NSString *const MGLEventSource = @"mapbox";
-
-// Event application state
-static NSString *const MGLApplicationStateForeground = @"Foreground";
-static NSString *const MGLApplicationStateBackground = @"Background";
-static NSString *const MGLApplicationStateInactive = @"Inactive";
-static NSString *const MGLApplicationStateUnknown = @"Unknown";
-
-const NSUInteger MGLMaximumEventsPerFlush = 180;
-const NSTimeInterval MGLFlushInterval = 180;
-
-@interface MGLMapboxEventsData : NSObject
-
-@property (nonatomic) NSString *vendorId;
-@property (nonatomic) NSString *model;
-@property (nonatomic) NSString *iOSVersion;
-@property (nonatomic) CGFloat scale;
-
-@end
-
-@implementation MGLMapboxEventsData
-
-- (instancetype)init {
- if (self = [super init]) {
- _vendorId = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
- _model = [self sysInfoByName:"hw.machine"];
- _iOSVersion = [NSString stringWithFormat:@"%@ %@", [UIDevice currentDevice].systemName, [UIDevice currentDevice].systemVersion];
- if ([UIScreen instancesRespondToSelector:@selector(nativeScale)]) {
- _scale = [UIScreen mainScreen].nativeScale;
- } else {
- _scale = [UIScreen mainScreen].scale;
- }
- }
- return self;
-}
-
-- (NSString *)sysInfoByName:(char *)typeSpecifier {
- size_t size;
- sysctlbyname(typeSpecifier, NULL, &size, NULL, 0);
-
- char *answer = malloc(size);
- sysctlbyname(typeSpecifier, answer, &size, NULL, 0);
-
- NSString *results = [NSString stringWithCString:answer encoding: NSUTF8StringEncoding];
-
- free(answer);
- return results;
-}
+@property (nonatomic) MMEEventsManager *eventsManager;
+@property (nonatomic) NSURL *baseURL;
+@property (nonatomic, copy) NSString *accessToken;
@end
+@implementation MGLMapboxEvents
-@interface MGLMapboxEvents () <MGLLocationManagerDelegate>
-
-@property (nonatomic) MGLMapboxEventsData *data;
-@property (nonatomic, copy) NSString *appBundleId;
-@property (nonatomic, readonly) NSString *instanceID;
-@property (nonatomic, copy) NSString *dateForDebugLogFile;
-@property (nonatomic) NSDateFormatter *rfc3339DateFormatter;
-@property (nonatomic) MGLAPIClient *apiClient;
-@property (nonatomic) BOOL usesTestServer;
-@property (nonatomic) BOOL canEnableDebugLogging;
-@property (nonatomic, getter=isPaused) BOOL paused;
-@property (nonatomic) NS_MUTABLE_ARRAY_OF(MGLMapboxEventAttributes *) *eventQueue;
-@property (nonatomic) dispatch_queue_t serialQueue;
-@property (nonatomic) dispatch_queue_t debugLogSerialQueue;
-@property (nonatomic) MGLLocationManager *locationManager;
-@property (nonatomic) NSTimer *timer;
-@property (nonatomic) NSDate *instanceIDRotationDate;
-@property (nonatomic) NSDate *nextTurnstileSendDate;
-@property (nonatomic) NSNumber *currentAccountTypeValue;
-@property (nonatomic) BOOL currentMetricsEnabledValue;
-
-@end
-
-@implementation MGLMapboxEvents {
- NSString *_instanceID;
- UIBackgroundTaskIdentifier _backgroundTaskIdentifier;
-}
+ (void)initialize {
if (self == [MGLMapboxEvents class]) {
NSBundle *bundle = [NSBundle mainBundle];
NSNumber *accountTypeNumber = [bundle objectForInfoDictionaryKey:MGLMapboxAccountType];
- [[NSUserDefaults standardUserDefaults] registerDefaults:@{
- MGLMapboxAccountType: accountTypeNumber ?: @0,
- MGLMapboxMetricsEnabled: @YES,
- @"MGLMapboxMetricsDebugLoggingEnabled": @NO,
- }];
+ [[NSUserDefaults standardUserDefaults] registerDefaults:@{MGLMapboxAccountType: accountTypeNumber ?: @0,
+ MGLMapboxMetricsEnabled: @YES,
+ MGLMapboxMetricsDebugLoggingEnabled: @NO}];
}
}
-+ (BOOL)isEnabled {
-#if TARGET_OS_SIMULATOR
- return NO;
-#else
- BOOL isLowPowerModeEnabled = NO;
- if ([NSProcessInfo instancesRespondToSelector:@selector(isLowPowerModeEnabled)]) {
- isLowPowerModeEnabled = [[NSProcessInfo processInfo] isLowPowerModeEnabled];
++ (nullable instancetype)sharedInstance {
+ if (NSProcessInfo.processInfo.mgl_isInterfaceBuilderDesignablesAgent) {
+ return nil;
}
- return ([[NSUserDefaults standardUserDefaults] boolForKey:MGLMapboxMetricsEnabled] &&
- [[NSUserDefaults standardUserDefaults] integerForKey:MGLMapboxAccountType] == 0 &&
- !isLowPowerModeEnabled);
-#endif
-}
-
-
-- (BOOL)debugLoggingEnabled {
- return (self.canEnableDebugLogging &&
- [[NSUserDefaults standardUserDefaults] boolForKey:@"MGLMapboxMetricsDebugLoggingEnabled"]);
+
+ static dispatch_once_t onceToken;
+ static MGLMapboxEvents *_sharedInstance;
+ dispatch_once(&onceToken, ^{
+ _sharedInstance = [[self alloc] init];
+ });
+ return _sharedInstance;
}
-- (instancetype) init {
+- (instancetype)init {
self = [super init];
if (self) {
- [MGLTelemetryConfig.sharedConfig configurationFromKey:[[NSUserDefaults standardUserDefaults] objectForKey:MGLMapboxMetricsProfile]];
+ _eventsManager = [[MMEEventsManager alloc] init];
+ _eventsManager.debugLoggingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:MGLMapboxMetricsDebugLoggingEnabled];
+ _eventsManager.accountType = [[NSUserDefaults standardUserDefaults] integerForKey:MGLMapboxAccountType];
+ _eventsManager.metricsEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:MGLMapboxMetricsEnabled];
- _currentAccountTypeValue = @0;
- _currentMetricsEnabledValue = YES;
-
- _appBundleId = [[NSBundle mainBundle] bundleIdentifier];
- _apiClient = [[MGLAPIClient alloc] init];
-
- NSString *uniqueID = [[NSProcessInfo processInfo] globallyUniqueString];
- _serialQueue = dispatch_queue_create([[NSString stringWithFormat:@"%@.%@.events.serial", _appBundleId, uniqueID] UTF8String], DISPATCH_QUEUE_SERIAL);
-
- _locationManager = [[MGLLocationManager alloc] init];
- _locationManager.delegate = self;
- _paused = YES;
- [self resumeMetricsCollection];
-
- // Events Control
- _eventQueue = [[NSMutableArray alloc] init];
-
- // Setup Date Format
- _rfc3339DateFormatter = [[NSDateFormatter alloc] init];
- NSLocale *enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];
-
- [_rfc3339DateFormatter setLocale:enUSPOSIXLocale];
- [_rfc3339DateFormatter setDateFormat:@"yyyy'-'MM'-'dd'T'HH':'mm':'ssZ"];
- // Clear Any System TimeZone Cache
- [NSTimeZone resetSystemTimeZone];
- [_rfc3339DateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
-
- // Configure logging
- if ([self isProbablyAppStoreBuild]) {
- self.canEnableDebugLogging = NO;
-
- if ([[NSUserDefaults standardUserDefaults] boolForKey:@"MGLMapboxMetricsDebugLoggingEnabled"]) {
- NSLog(@"Telemetry logging is only enabled in non-app store builds.");
- }
- } else {
- self.canEnableDebugLogging = YES;
+ // It is possible for the shared instance of this class to be created because of a call to
+ // +[MGLAccountManager load] early on in the app lifecycle of the host application.
+ // If user default values for access token and base URL are available, they are stored here
+ // on local properties so that they can be applied later once MMEEventsManager is fully initialized
+ // (once -[MMEEventsManager initializeWithAccessToken:userAgentBase:hostSDKVersion:] is called.
+ // Normally, the telem access token and base URL are not set this way. However, overriding these values
+ // with user defaults can be useful for testing with an alternative (test) backend system.
+ if ([[[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] allKeys] containsObject:MGLTelemetryAccessToken]) {
+ self.accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:MGLTelemetryAccessToken];
}
-
- // Watch for changes to telemetry settings by the user
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDefaultsDidChange:) name:NSUserDefaultsDidChangeNotification object:nil];
-
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pauseOrResumeMetricsCollectionIfRequired) name:UIApplicationDidEnterBackgroundNotification object:nil];
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pauseOrResumeMetricsCollectionIfRequired) name:UIApplicationDidBecomeActiveNotification object:nil];
-
- // Watch for Low Power Mode change events
- if (&NSProcessInfoPowerStateDidChangeNotification != NULL) {
- [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(pauseOrResumeMetricsCollectionIfRequired) name:NSProcessInfoPowerStateDidChangeNotification object:nil];
+ if ([[[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] allKeys] containsObject:MGLTelemetryBaseURL]) {
+ self.baseURL = [NSURL URLWithString:[[NSUserDefaults standardUserDefaults] objectForKey:MGLTelemetryBaseURL]];
}
+
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDefaultsDidChange:) name:NSUserDefaultsDidChangeNotification object:nil];
}
return self;
}
-// Called implicitly from any public class convenience methods.
-// May return nil if this feature is disabled.
-//
-+ (nullable instancetype)sharedManager {
- if (NSProcessInfo.processInfo.mgl_isInterfaceBuilderDesignablesAgent) {
- return nil;
- }
- static dispatch_once_t onceToken;
- static MGLMapboxEvents *_sharedManager;
- dispatch_once(&onceToken, ^{
- _sharedManager = [[self alloc] init];
- });
- return _sharedManager;
-}
-
- (void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self];
- [self pauseMetricsCollection];
}
-- (NSString *)instanceID {
- if (self.instanceIDRotationDate && [[NSDate date] timeIntervalSinceDate:self.instanceIDRotationDate] >= 0) {
- _instanceID = nil;
+- (void)userDefaultsDidChange:(NSNotification *)notification {
+ dispatch_async(dispatch_get_main_queue(), ^{
+ [self updateNonDisablingConfigurationValues];
+ [self updateDisablingConfigurationValuesWithNotification:notification];
+ });
+}
+
+- (void)updateNonDisablingConfigurationValues {
+ self.eventsManager.debugLoggingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"MGLMapboxMetricsDebugLoggingEnabled"];
+
+ // It is possible for `MGLTelemetryAccessToken` to have been set yet `userDefaultsDidChange:`
+ // is called before `setupWithAccessToken:` is called.
+ // In that case, setting the access token here will have no effect. In practice, that's fine
+ // because the access token value will be resolved when `setupWithAccessToken:` is called eventually
+ if ([[[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] allKeys] containsObject:MGLTelemetryAccessToken]) {
+ self.eventsManager.accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:MGLTelemetryAccessToken];
}
- if (!_instanceID) {
- _instanceID = [[NSUUID UUID] UUIDString];
- NSTimeInterval twentyFourHourTimeInterval = 24 * 3600;
- self.instanceIDRotationDate = [[NSDate date] dateByAddingTimeInterval:twentyFourHourTimeInterval];
+
+ // It is possible for `MGLTelemetryBaseURL` to have been set yet `userDefaultsDidChange:`
+ // is called before setupWithAccessToken: is called.
+ // In that case, setting the base URL here will have no effect. In practice, that's fine
+ // because the base URL value will be resolved when `setupWithAccessToken:` is called eventually
+ if ([[[[NSUserDefaults standardUserDefaults] dictionaryRepresentation] allKeys] containsObject:MGLTelemetryBaseURL]) {
+ NSURL *baseURL = [NSURL URLWithString:[[NSUserDefaults standardUserDefaults] objectForKey:MGLTelemetryBaseURL]];
+ self.eventsManager.baseURL = baseURL;
}
- return _instanceID;
}
-- (void)userDefaultsDidChange:(NSNotification *)notification {
-
+- (void)updateDisablingConfigurationValuesWithNotification:(NSNotification *)notification {
// Guard against over calling pause / resume if the values this implementation actually
- // cares about have not changed
-
+ // cares about have not changed. We guard because the pause and resume method checks CoreLocation's
+ // authorization status and that can drag on the main thread if done too many times (e.g. if the host
+ // app heavily uses the user defaults API and this method is called very frequently)
if ([[notification object] respondsToSelector:@selector(objectForKey:)]) {
NSUserDefaults *userDefaults = [notification object];
- NSNumber *accountType = [userDefaults objectForKey:MGLMapboxAccountType];
- BOOL metricsEnabled = [[userDefaults objectForKey:MGLMapboxMetricsEnabled] boolValue];
-
- if (![accountType isEqualToNumber:self.currentAccountTypeValue] || metricsEnabled != self.currentMetricsEnabledValue) {
- [self pauseOrResumeMetricsCollectionIfRequired];
- self.currentAccountTypeValue = accountType;
- self.currentMetricsEnabledValue = metricsEnabled;
- }
- }
-
-}
-
-- (void)pauseOrResumeMetricsCollectionIfRequired {
-
- // [CLLocationManager authorizationStatus] has been found to block in some cases so
- // dispatch the call to a non-UI thread
- dispatch_async(self.serialQueue, ^{
- CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
+ NSInteger accountType = [userDefaults integerForKey:MGLMapboxAccountType];
+ BOOL metricsEnabled = [userDefaults boolForKey:MGLMapboxMetricsEnabled];
- // Checking application state must be done on the main thread for safety and
- // to avoid a thread sanitizer error
- dispatch_async(dispatch_get_main_queue(), ^{
- UIApplication *application = [UIApplication sharedApplication];
- UIApplicationState state = application.applicationState;
-
- // Prevent blue status bar when host app has `when in use` permission only and it is not in foreground
- if (status == kCLAuthorizationStatusAuthorizedWhenInUse && state == UIApplicationStateBackground) {
- if (_backgroundTaskIdentifier == UIBackgroundTaskInvalid) {
- _backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^{
- [application endBackgroundTask:_backgroundTaskIdentifier];
- _backgroundTaskIdentifier = UIBackgroundTaskInvalid;
- }];
- [self flush];
- }
- [self pauseMetricsCollection];
- return;
- }
+ if (accountType != self.eventsManager.accountType || metricsEnabled != self.eventsManager.metricsEnabled) {
+ self.eventsManager.accountType = accountType;
+ self.eventsManager.metricsEnabled = metricsEnabled;
- // Toggle pause based on current pause state, user opt-out state, and low-power state.
- BOOL enabled = [[self class] isEnabled];
- if (self.paused && enabled) {
- [self resumeMetricsCollection];
- } else if (!self.paused && !enabled) {
- [self flush];
- [self pauseMetricsCollection];
- }
- });
- });
-}
-
-- (void)pauseMetricsCollection {
- if (self.paused) {
- return;
- }
-
- self.paused = YES;
- [self.timer invalidate];
- self.timer = nil;
- [self.eventQueue removeAllObjects];
- self.data = nil;
-
- [self.locationManager stopUpdatingLocation];
-}
-
-- (void)resumeMetricsCollection {
- if (!self.paused || ![[self class] isEnabled]) {
- return;
- }
-
- self.paused = NO;
- self.data = [[MGLMapboxEventsData alloc] init];
-
- [self.locationManager startUpdatingLocation];
-}
-
-+ (void)flush {
- [[MGLMapboxEvents sharedManager] flush];
-}
-
-- (void)flush {
- if ([MGLAccountManager accessToken] == nil) {
- return;
- }
-
- NSArray *events = [NSArray arrayWithArray:self.eventQueue];
- [self.eventQueue removeAllObjects];
-
- [self postEvents:events];
-
- if (self.timer) {
- [self.timer invalidate];
- self.timer = nil;
- }
-
- [self pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription:@"flush"}];
-}
-
-- (void)pushTurnstileEvent {
- if (self.nextTurnstileSendDate && [[NSDate date] timeIntervalSinceDate:self.nextTurnstileSendDate] < 0) {
- return;
- }
-
- NSString *vendorID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
- if (!vendorID) {
- return;
- }
-
- NSDictionary *turnstileEventAttributes = @{MGLEventKeyEvent: MGLEventTypeAppUserTurnstile,
- MGLEventKeyCreated: [self.rfc3339DateFormatter stringFromDate:[NSDate date]],
- MGLEventKeyVendorID: vendorID,
- MGLEventKeyEnabledTelemetry: @([[self class] isEnabled])};
-
- if ([MGLAccountManager accessToken] == nil) {
- return;
- }
-
- __weak __typeof__(self) weakSelf = self;
- [self.apiClient postEvent:turnstileEventAttributes completionHandler:^(NSError * _Nullable error) {
- __strong __typeof__(weakSelf) strongSelf = weakSelf;
- if (error) {
- [strongSelf pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription: @"Network error",
- @"error": error}];
- return;
+ [self.eventsManager pauseOrResumeMetricsCollectionIfRequired];
}
- [strongSelf writeEventToLocalDebugLog:turnstileEventAttributes];
- [strongSelf updateNextTurnstileSendDate];
- }];
-}
-
-- (void)updateNextTurnstileSendDate {
- // Find the time a day from now (sometime tomorrow)
- NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
- NSDateComponents *dayComponent = [[NSDateComponents alloc] init];
- dayComponent.day = 1;
- NSDate *sometimeTomorrow = [calendar dateByAddingComponents:dayComponent toDate:[NSDate date] options:0];
-
- // Find the start of tomorrow and use that as the next turnstile send date. The effect of this is that
- // turnstile events can be sent as much as once per calendar day and always at the start of a session
- // when a map load happens.
- NSDate *startOfTomorrow = nil;
- [calendar rangeOfUnit:NSCalendarUnitDay startDate:&startOfTomorrow interval:nil forDate:sometimeTomorrow];
- self.nextTurnstileSendDate = startOfTomorrow;
-}
-
-+ (void)pushEvent:(NSString *)event withAttributes:(MGLMapboxEventAttributes *)attributeDictionary {
- [[MGLMapboxEvents sharedManager] pushEvent:event withAttributes:attributeDictionary];
-}
-
-- (void)pushEvent:(NSString *)event withAttributes:(MGLMapboxEventAttributes *)attributeDictionary {
- if (!event) {
- return;
- }
-
- if ([event isEqualToString:MGLEventTypeMapLoad]) {
- [self pushTurnstileEvent];
- }
-
- if (self.paused) {
- return;
- }
-
- MGLMapboxEventAttributes *fullyFormedEvent = [self fullyFormedEventForEvent:event withAttributes:attributeDictionary];
- if (fullyFormedEvent) {
- [self.eventQueue addObject:fullyFormedEvent];
- [self writeEventToLocalDebugLog:fullyFormedEvent];
- // Has Flush Limit Been Reached?
- if (self.eventQueue.count >= MGLMaximumEventsPerFlush) {
- [self flush];
- } else if (self.eventQueue.count == 1) {
- // If this is first new event on queue start timer,
- [self startTimer];
- }
- } else {
- [self pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription: @"Unknown event",
- @"eventName": event,
- @"event.attributes": attributeDictionary}];
- }
-}
-
-#pragma mark Events
-
-- (MGLMapboxEventAttributes *)fullyFormedEventForEvent:(NSString *)event withAttributes:(MGLMapboxEventAttributes *)attributeDictionary {
- if ([event isEqualToString:MGLEventTypeMapLoad]) {
- return [self mapLoadEventWithAttributes:attributeDictionary];
- } else if ([event isEqualToString:MGLEventTypeMapTap]) {
- return [self mapClickEventWithAttributes:attributeDictionary];
- } else if ([event isEqualToString:MGLEventTypeMapDragEnd]) {
- return [self mapDragEndEventWithAttributes:attributeDictionary];
- } else if ([event isEqualToString:MGLEventTypeLocation]) {
- return [self locationEventWithAttributes:attributeDictionary];
}
- return nil;
-}
-
-- (MGLMapboxEventAttributes *)locationEventWithAttributes:(MGLMapboxEventAttributes *)attributeDictionary {
- MGLMutableMapboxEventAttributes *attributes = [NSMutableDictionary dictionary];
- attributes[MGLEventKeyEvent] = MGLEventTypeLocation;
- attributes[MGLEventKeySource] = MGLEventSource;
- attributes[MGLEventKeySessionId] = self.instanceID;
- attributes[MGLEventKeyOperatingSystem] = self.data.iOSVersion;
- NSString *currentApplicationState = [self applicationState];
- if (![currentApplicationState isEqualToString:MGLApplicationStateUnknown]) {
- attributes[MGLEventKeyApplicationState] = currentApplicationState;
- }
-
- return [self eventForAttributes:attributes attributeDictionary:attributeDictionary];
-}
-
-- (MGLMapboxEventAttributes *)mapLoadEventWithAttributes:(MGLMapboxEventAttributes *)attributeDictionary {
- MGLMutableMapboxEventAttributes *attributes = [NSMutableDictionary dictionary];
- attributes[MGLEventKeyEvent] = MGLEventTypeMapLoad;
- attributes[MGLEventKeyCreated] = [self.rfc3339DateFormatter stringFromDate:[NSDate date]];
- attributes[MGLEventKeyVendorID] = self.data.vendorId;
- attributes[MGLEventKeyModel] = self.data.model;
- attributes[MGLEventKeyOperatingSystem] = self.data.iOSVersion;
- attributes[MGLEventKeyResolution] = @(self.data.scale);
- attributes[MGLEventKeyAccessibilityFontScale] = @([self contentSizeScale]);
- attributes[MGLEventKeyOrientation] = [self deviceOrientation];
- attributes[MGLEventKeyWifi] = @([[MGLReachability reachabilityForLocalWiFi] isReachableViaWiFi]);
-
- return [self eventForAttributes:attributes attributeDictionary:attributeDictionary];
-}
-
-- (MGLMapboxEventAttributes *)mapClickEventWithAttributes:(MGLMapboxEventAttributes *)attributeDictionary {
- MGLMutableMapboxEventAttributes *attributes = [self interactionEvent];
- attributes[MGLEventKeyEvent] = MGLEventTypeMapTap;
- return [self eventForAttributes:attributes attributeDictionary:attributeDictionary];
-}
-
-- (MGLMapboxEventAttributes *)mapDragEndEventWithAttributes:(MGLMapboxEventAttributes *)attributeDictionary {
- MGLMutableMapboxEventAttributes *attributes = [self interactionEvent];
- attributes[MGLEventKeyEvent] = MGLEventTypeMapDragEnd;
-
- return [self eventForAttributes:attributes attributeDictionary:attributeDictionary];
}
-- (MGLMutableMapboxEventAttributes *)interactionEvent {
- MGLMutableMapboxEventAttributes *attributes = [NSMutableDictionary dictionary];
- attributes[MGLEventKeyCreated] = [self.rfc3339DateFormatter stringFromDate:[NSDate date]];
- attributes[MGLEventKeyOrientation] = [self deviceOrientation];
- attributes[MGLEventKeyWifi] = @([[MGLReachability reachabilityForLocalWiFi] isReachableViaWiFi]);
-
- return attributes;
-}
-
-- (MGLMapboxEventAttributes *)eventForAttributes:(MGLMutableMapboxEventAttributes *)attributes attributeDictionary:(MGLMapboxEventAttributes *)attributeDictionary {
- [attributes addEntriesFromDictionary:attributeDictionary];
-
- return [attributes copy];
-}
-
-// Called implicitly from public use of +flush.
-//
-- (void)postEvents:(NS_ARRAY_OF(MGLMapboxEventAttributes *) *)events {
- if (self.paused) {
- return;
++ (void)setupWithAccessToken:(NSString *)accessToken {
+ NSString *semanticVersion = [NSBundle mgl_frameworkInfoDictionary][@"MGLSemanticVersionString"];
+ NSString *shortVersion = [NSBundle mgl_frameworkInfoDictionary][@"CFBundleShortVersionString"];
+ NSString *sdkVersion = semanticVersion ?: shortVersion;
+
+ // It is possible that an alternative access token was already set on this instance when the class was loaded
+ // Use it if it exists
+ NSString *resolvedAccessToken = [MGLMapboxEvents sharedInstance].accessToken ?: accessToken;
+
+ [[[self sharedInstance] eventsManager] initializeWithAccessToken:resolvedAccessToken userAgentBase:MGLAPIClientUserAgentBase hostSDKVersion:sdkVersion];
+
+ // It is possible that an alternative base URL was set on this instance when the class was loaded
+ // Use it if it exists
+ if ([MGLMapboxEvents sharedInstance].baseURL) {
+ [[MGLMapboxEvents sharedInstance] eventsManager].baseURL = [MGLMapboxEvents sharedInstance].baseURL;
}
-
- __weak __typeof__(self) weakSelf = self;
- dispatch_async(self.serialQueue, ^{
- __strong __typeof__(weakSelf) strongSelf = weakSelf;
- [self.apiClient postEvents:events completionHandler:^(NSError * _Nullable error) {
- if (error) {
- [strongSelf pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription: @"Network error",
- @"error": error}];
- } else {
- [strongSelf pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription: @"post",
- @"debug.eventsCount": @(events.count)}];
- }
- [[UIApplication sharedApplication] endBackgroundTask:_backgroundTaskIdentifier];
- _backgroundTaskIdentifier = UIBackgroundTaskInvalid;
- }];
- });
-}
-
-- (void)startTimer {
- [self.timer invalidate];
- self.timer = [NSTimer scheduledTimerWithTimeInterval:MGLFlushInterval
- target:self
- selector:@selector(flush)
- userInfo:nil
- repeats:YES];
}
-- (NSString *)deviceOrientation {
- NSString *result;
-
- switch ([UIDevice currentDevice].orientation) {
- case UIDeviceOrientationUnknown:
- result = @"Unknown";
- break;
- case UIDeviceOrientationPortrait:
- result = @"Portrait";
- break;
- case UIDeviceOrientationPortraitUpsideDown:
- result = @"PortraitUpsideDown";
- break;
- case UIDeviceOrientationLandscapeLeft:
- result = @"LandscapeLeft";
- break;
- case UIDeviceOrientationLandscapeRight:
- result = @"LandscapeRight";
- break;
- case UIDeviceOrientationFaceUp:
- result = @"FaceUp";
- break;
- case UIDeviceOrientationFaceDown:
- result = @"FaceDown";
- break;
- default:
- result = @"Default - Unknown";
- break;
- }
-
- return result;
++ (void)pushTurnstileEvent {
+ [[[self sharedInstance] eventsManager] sendTurnstileEvent];
}
-- (NSString *)applicationState {
- switch ([UIApplication sharedApplication].applicationState) {
- case UIApplicationStateActive:
- return MGLApplicationStateForeground;
- case UIApplicationStateInactive:
- return MGLApplicationStateInactive;
- case UIApplicationStateBackground:
- return MGLApplicationStateBackground;
- default:
- return MGLApplicationStateUnknown;
- }
++ (void)pushEvent:(NSString *)event withAttributes:(MMEMapboxEventAttributes *)attributeDictionary {
+ [[[self sharedInstance] eventsManager] enqueueEventWithName:event attributes:attributeDictionary];
}
-- (NSInteger)contentSizeScale {
- NSInteger result = -9999;
-
- NSString *sc = [UIApplication sharedApplication].preferredContentSizeCategory;
-
- if ([sc isEqualToString:UIContentSizeCategoryExtraSmall]) {
- result = -3;
- } else if ([sc isEqualToString:UIContentSizeCategorySmall]) {
- result = -2;
- } else if ([sc isEqualToString:UIContentSizeCategoryMedium]) {
- result = -1;
- } else if ([sc isEqualToString:UIContentSizeCategoryLarge]) {
- result = 0;
- } else if ([sc isEqualToString:UIContentSizeCategoryExtraLarge]) {
- result = 1;
- } else if ([sc isEqualToString:UIContentSizeCategoryExtraExtraLarge]) {
- result = 2;
- } else if ([sc isEqualToString:UIContentSizeCategoryExtraExtraExtraLarge]) {
- result = 3;
- } else if ([sc isEqualToString:UIContentSizeCategoryAccessibilityMedium]) {
- result = -11;
- } else if ([sc isEqualToString:UIContentSizeCategoryAccessibilityLarge]) {
- result = 10;
- } else if ([sc isEqualToString:UIContentSizeCategoryAccessibilityExtraLarge]) {
- result = 11;
- } else if ([sc isEqualToString:UIContentSizeCategoryAccessibilityExtraExtraLarge]) {
- result = 12;
- } else if ([sc isEqualToString:UIContentSizeCategoryAccessibilityExtraExtraExtraLarge]) {
- result = 13;
- }
-
- return result;
++ (void)flush {
+ [[[self sharedInstance] eventsManager] flush];
}
+ (void)ensureMetricsOptoutExists {
NSNumber *shownInAppNumber = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"MGLMapboxMetricsEnabledSettingShownInApp"];
BOOL metricsEnabledSettingShownInAppFlag = [shownInAppNumber boolValue];
-
+
if (!metricsEnabledSettingShownInAppFlag &&
[[NSUserDefaults standardUserDefaults] integerForKey:MGLMapboxAccountType] == 0) {
// Opt-out is not configured in UI, so check for Settings.bundle
id defaultEnabledValue;
NSString *appSettingsBundle = [[NSBundle mainBundle] pathForResource:@"Settings" ofType:@"bundle"];
-
+
if (appSettingsBundle) {
// Dynamic Settings.bundle loading based on http://stackoverflow.com/a/510329/2094275
NSDictionary *settings = [NSDictionary dictionaryWithContentsOfFile:[appSettingsBundle stringByAppendingPathComponent:@"Root.plist"]];
@@ -651,7 +171,7 @@ const NSTimeInterval MGLFlushInterval = 180;
}
}
}
-
+
if (!defaultEnabledValue) {
[NSException raise:@"Telemetry opt-out missing" format:
@"End users must be able to opt out of Mapbox Telemetry in your app, either inside Settings (via Settings.bundle) or inside this app. "
@@ -663,153 +183,4 @@ const NSTimeInterval MGLFlushInterval = 180;
}
}
-#pragma mark CLLocationManagerUtilityDelegate
-
-- (void)locationManager:(MGLLocationManager *)locationManager didUpdateLocations:(NSArray *)locations {
- for (CLLocation *loc in locations) {
- double accuracy = 10000000;
- double lat = floor(loc.coordinate.latitude * accuracy) / accuracy;
- double lng = floor(loc.coordinate.longitude * accuracy) / accuracy;
- double horizontalAccuracy = round(loc.horizontalAccuracy);
- NSString *formattedDate = [self.rfc3339DateFormatter stringFromDate:loc.timestamp];
- [MGLMapboxEvents pushEvent:MGLEventTypeLocation withAttributes:@{MGLEventKeyCreated: formattedDate,
- MGLEventKeyLatitude: @(lat),
- MGLEventKeyLongitude: @(lng),
- MGLEventKeyAltitude: @(round(loc.altitude)),
- MGLEventHorizontalAccuracy: @(horizontalAccuracy)}];
- }
-}
-
-- (void)locationManagerBackgroundLocationUpdatesDidAutomaticallyPause:(MGLLocationManager *)locationManager {
- [self pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription:@"locationManager.locationManagerAutoPause"}];
-}
-
-- (void)locationManagerBackgroundLocationUpdatesDidTimeout:(MGLLocationManager *)locationManager {
- [self pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription:@"locationManager.locationManagerTimeout"}];
-}
-
-- (void)locationManagerDidStartLocationUpdates:(MGLLocationManager *)locationManager {
- [self pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription:@"locationManager.locationManagerStartUpdates"}];
-}
-
-- (void)locationManagerDidStopLocationUpdates:(MGLLocationManager *)locationManager {
- [self pushDebugEvent:MGLEventTypeLocalDebug withAttributes:@{MGLEventKeyLocalDebugDescription: @"locationManager.locationManagerStopUpdates"}];
-}
-
-#pragma mark MGLMapboxEvents Debug
-
-- (void)pushDebugEvent:(NSString *)event withAttributes:(MGLMapboxEventAttributes *)attributeDictionary {
- if (![self debugLoggingEnabled]) {
- return;
- }
-
- if (!event) {
- return;
- }
-
- MGLMutableMapboxEventAttributes *evt = [MGLMutableMapboxEventAttributes dictionaryWithDictionary:attributeDictionary];
- [evt setObject:event forKey:@"event"];
- [evt setObject:[self.rfc3339DateFormatter stringFromDate:[NSDate date]] forKey:@"created"];
- [evt setValue:[self applicationState] forKey:@"applicationState"];
- [evt setValue:@([[self class] isEnabled]) forKey:@"telemetryEnabled"];
- [evt setObject:self.instanceID forKey:@"instance"];
-
- MGLMapboxEventAttributes *finalEvent = [NSDictionary dictionaryWithDictionary:evt];
- [self writeEventToLocalDebugLog:finalEvent];
-}
-
-- (void)writeEventToLocalDebugLog:(MGLMapboxEventAttributes *)event {
- if (![self debugLoggingEnabled]) {
- return;
- }
-
- NSLog(@"%@", [self stringForDebugEvent:event]);
-
- if (!self.dateForDebugLogFile) {
- NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
- [dateFormatter setDateFormat:@"yyyy'-'MM'-'dd"];
- [dateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
- self.dateForDebugLogFile = [dateFormatter stringFromDate:[NSDate date]];
- }
-
- if (!self.debugLogSerialQueue) {
- NSString *uniqueID = [[NSProcessInfo processInfo] globallyUniqueString];
- self.debugLogSerialQueue = dispatch_queue_create([[NSString stringWithFormat:@"%@.%@.events.debugLog", _appBundleId, uniqueID] UTF8String], DISPATCH_QUEUE_SERIAL);
- }
-
- dispatch_async(self.debugLogSerialQueue, ^{
- if ([NSJSONSerialization isValidJSONObject:event]) {
- NSData *jsonData = [NSJSONSerialization dataWithJSONObject:event options:NSJSONWritingPrettyPrinted error:nil];
-
- NSString *jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
- jsonString = [jsonString stringByAppendingString:@",\n"];
-
- NSString *logFilePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:[NSString stringWithFormat:@"telemetry_log-%@.json", self.dateForDebugLogFile]];
-
- NSFileManager *fileManager = [[NSFileManager alloc] init];
- if ([fileManager fileExistsAtPath:logFilePath]) {
- NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:logFilePath];
- [fileHandle seekToEndOfFile];
- [fileHandle writeData:[jsonString dataUsingEncoding:NSUTF8StringEncoding]];
- } else {
- [fileManager createFileAtPath:logFilePath contents:[jsonString dataUsingEncoding:NSUTF8StringEncoding] attributes:@{ NSFileProtectionKey: NSFileProtectionCompleteUntilFirstUserAuthentication }];
- }
- }
- });
-}
-
-- (NSString *)stringForDebugEvent:(MGLMapboxEventAttributes *)event {
- // redact potentially sensitive location details from system console log
- if ([event[@"event"] isEqualToString:MGLEventTypeLocation]) {
- MGLMutableMapboxEventAttributes *evt = [MGLMutableMapboxEventAttributes dictionaryWithDictionary:event];
- [evt setObject:@"<redacted>" forKey:@"lat"];
- [evt setObject:@"<redacted>" forKey:@"lng"];
- event = evt;
- }
-
- return [NSString stringWithFormat:@"Mapbox Telemetry event %@", event];
-}
-
-- (BOOL)isProbablyAppStoreBuild {
-#if TARGET_IPHONE_SIMULATOR
- return NO;
-#else
- // BugshotKit by Marco Arment https://github.com/marcoarment/BugshotKit/
- // Adapted from https://github.com/blindsightcorp/BSMobileProvision
-
- NSString *binaryMobileProvision = [NSString stringWithContentsOfFile:[NSBundle.mainBundle pathForResource:@"embedded" ofType:@"mobileprovision"] encoding:NSISOLatin1StringEncoding error:NULL];
- if (!binaryMobileProvision) {
- return YES; // no provision
- }
-
- NSScanner *scanner = [NSScanner scannerWithString:binaryMobileProvision];
- NSString *plistString;
- if (![scanner scanUpToString:@"<plist" intoString:nil] || ! [scanner scanUpToString:@"</plist>" intoString:&plistString]) {
- return YES; // no XML plist found in provision
- }
- plistString = [plistString stringByAppendingString:@"</plist>"];
-
- NSData *plistdata_latin1 = [plistString dataUsingEncoding:NSISOLatin1StringEncoding];
- NSError *error = nil;
- NSDictionary *mobileProvision = [NSPropertyListSerialization propertyListWithData:plistdata_latin1 options:NSPropertyListImmutable format:NULL error:&error];
- if (error) {
- return YES; // unknown plist format
- }
-
- if (!mobileProvision || ! mobileProvision.count) {
- return YES; // no entitlements
- }
-
- if (mobileProvision[@"ProvisionsAllDevices"]) {
- return NO; // enterprise provisioning
- }
-
- if (mobileProvision[@"ProvisionedDevices"] && [mobileProvision[@"ProvisionedDevices"] count]) {
- return NO; // development or ad-hoc
- }
-
- return YES; // expected development/enterprise/ad-hoc entitlements not found
-#endif
-}
-
@end
diff --git a/platform/ios/src/MGLTelemetryConfig.h b/platform/ios/src/MGLTelemetryConfig.h
index 527d344291..96e525c969 100644
--- a/platform/ios/src/MGLTelemetryConfig.h
+++ b/platform/ios/src/MGLTelemetryConfig.h
@@ -9,7 +9,7 @@ NS_ASSUME_NONNULL_BEGIN
extern NSString *const MGLMapboxMetricsProfile;
-+ (nullable instancetype)sharedConfig;
+@property (class, nullable, nonatomic, readonly) MGLTelemetryConfig *sharedConfig;
- (void)configurationFromKey:(NSString *)key;
diff --git a/platform/ios/src/Mapbox-Prefix.pch b/platform/ios/src/Mapbox-Prefix.pch
new file mode 100644
index 0000000000..6754020861
--- /dev/null
+++ b/platform/ios/src/Mapbox-Prefix.pch
@@ -0,0 +1 @@
+#import "MMENamespacedDependencies.h"
diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h
index 11720ac68e..20417dbbd4 100644
--- a/platform/ios/src/Mapbox.h
+++ b/platform/ios/src/Mapbox.h
@@ -51,11 +51,10 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
#import "MGLOpenGLStyleLayer.h"
#import "MGLSource.h"
#import "MGLTileSource.h"
-#import "MGLVectorSource.h"
+#import "MGLVectorTileSource.h"
#import "MGLShapeSource.h"
-#import "MGLAbstractShapeSource.h"
#import "MGLComputedShapeSource.h"
-#import "MGLRasterSource.h"
+#import "MGLRasterTileSource.h"
#import "MGLRasterDEMSource.h"
#import "MGLImageSource.h"
#import "MGLTilePyramidOfflineRegion.h"
diff --git a/platform/ios/src/UIColor+MGLAdditions.h b/platform/ios/src/UIColor+MGLAdditions.h
index ea415d9db9..60cfe1c58b 100644
--- a/platform/ios/src/UIColor+MGLAdditions.h
+++ b/platform/ios/src/UIColor+MGLAdditions.h
@@ -12,3 +12,10 @@
+ (UIColor *)mgl_colorWithColor:(mbgl::Color)color;
@end
+
+@interface NSExpression (MGLColorAdditions)
+
++ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components;
++ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components;
+
+@end
diff --git a/platform/ios/src/UIColor+MGLAdditions.mm b/platform/ios/src/UIColor+MGLAdditions.mm
index 41c066c206..9ca39acda4 100644
--- a/platform/ios/src/UIColor+MGLAdditions.mm
+++ b/platform/ios/src/UIColor+MGLAdditions.mm
@@ -21,3 +21,52 @@
}
@end
+
+@implementation NSExpression (MGLColorAdditions)
+
++ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components {
+ if (UIColor *color = [self mgl_colorWithRGBComponents:components]) {
+ return [NSExpression expressionForConstantValue:color];
+ }
+
+ NSExpression *color = [NSExpression expressionForConstantValue:[UIColor class]];
+ NSExpression *alpha = [NSExpression expressionForConstantValue:@1.0];
+ return [NSExpression expressionForFunction:color
+ selectorName:@"colorWithRed:green:blue:alpha:"
+ arguments:[components arrayByAddingObject:alpha]];
+}
+
++ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components {
+ if (UIColor *color = [self mgl_colorWithRGBComponents:components]) {
+ return [NSExpression expressionForConstantValue:color];
+ }
+
+ NSExpression *color = [NSExpression expressionForConstantValue:[UIColor class]];
+ return [NSExpression expressionForFunction:color
+ selectorName:@"colorWithRed:green:blue:alpha:"
+ arguments:components];
+}
+
++ (UIColor *)mgl_colorWithRGBComponents:(NSArray<NSExpression *> *)components {
+ if (components.count < 3 || components.count > 4) {
+ return nil;
+ }
+
+ for (NSExpression *component in components) {
+ if (component.expressionType != NSConstantValueExpressionType) {
+ return nil;
+ }
+
+ NSNumber *number = (NSNumber *)component.constantValue;
+ if (![number isKindOfClass:[NSNumber class]]) {
+ return nil;
+ }
+ }
+
+ return [UIColor colorWithRed:[components[0].constantValue doubleValue] / 255.0
+ green:[components[1].constantValue doubleValue] / 255.0
+ blue:[components[2].constantValue doubleValue] / 255.0
+ alpha:components.count == 3 ? [components[3].constantValue doubleValue] : 1.0];
+}
+
+@end
diff --git a/platform/ios/test/MGLAnnotationViewTests.m b/platform/ios/test/MGLAnnotationViewTests.m
index fc4f35a9e1..2f5963e66e 100644
--- a/platform/ios/test/MGLAnnotationViewTests.m
+++ b/platform/ios/test/MGLAnnotationViewTests.m
@@ -49,7 +49,7 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReu
_didCallDismissCalloutAnimated = YES;
}
-- (void)presentCalloutFromRect:(CGRect)rect inView:(UIView *)view constrainedToView:(UIView *)constrainedView animated:(BOOL)animated { }
+- (void)presentCalloutFromRect:(CGRect)rect inView:(nonnull UIView *)view constrainedToRect:(CGRect)constrainedRect animated:(BOOL)animated {}
@end
@@ -57,6 +57,7 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReu
@property (nonatomic) XCTestExpectation *expectation;
@property (nonatomic) MGLMapView *mapView;
@property (nonatomic, weak) MGLAnnotationView *annotationView;
+@property (nonatomic) NSInteger annotationSelectedCount;
@end
@implementation MGLAnnotationViewTests
@@ -98,6 +99,61 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReu
XCTAssertNotNil(customAnnotationView);
}
+- (void)testSelectingOffscreenAnnotation
+{
+ // Partial test for https://github.com/mapbox/mapbox-gl-native/issues/9790
+
+ // This isn't quite the same as in updateAnnotationViews, but should be sufficient for this test.
+ MGLCoordinateBounds coordinateBounds = [_mapView convertRect:_mapView.bounds toCoordinateBoundsFromView:_mapView];
+
+ // -90 latitude is invalid. TBD.
+ BOOL anyOffscreen = NO;
+ NSInteger selectionCount = 0;
+
+ for (NSInteger latitude = -89; latitude <= 90; latitude += 10)
+ {
+ for (NSInteger longitude = -180; longitude <= 180; longitude += 10)
+ {
+ MGLTestAnnotation *annotation = [[MGLTestAnnotation alloc] init];
+
+ annotation.coordinate = CLLocationCoordinate2DMake(latitude, longitude);
+ [_mapView addAnnotation:annotation];
+
+ if (!(MGLCoordinateInCoordinateBounds(annotation.coordinate, coordinateBounds)))
+ anyOffscreen = YES;
+
+ XCTAssertNil(_mapView.selectedAnnotations.firstObject, @"There should be no selected annotation");
+
+ // First selection
+ [_mapView selectAnnotation:annotation animated:NO];
+ selectionCount++;
+
+ XCTAssert(_mapView.selectedAnnotations.count == 1, @"There should only be 1 selected annotation");
+ XCTAssertEqualObjects(_mapView.selectedAnnotations.firstObject, annotation, @"The annotation should be selected");
+
+ // Deselect
+ [_mapView deselectAnnotation:annotation animated:NO];
+ XCTAssert(_mapView.selectedAnnotations.count == 0, @"There should be no selected annotations");
+
+ // Second selection
+ _mapView.selectedAnnotations = @[annotation];
+ selectionCount++;
+
+ XCTAssert(_mapView.selectedAnnotations.count == 1, @"There should be 1 selected annotation");
+ XCTAssertEqualObjects(_mapView.selectedAnnotations.firstObject, annotation, @"The annotation should be selected");
+
+ // Deselect
+ [_mapView deselectAnnotation:annotation animated:NO];
+ XCTAssert(_mapView.selectedAnnotations.count == 0, @"There should be no selected annotations");
+ }
+ }
+
+ XCTAssert(anyOffscreen, @"At least one of these annotations should be offscreen");
+ XCTAssertEqual(selectionCount, self.annotationSelectedCount, @"-mapView:didSelectAnnotation: should be called for each selection");
+}
+
+#pragma mark - MGLMapViewDelegate -
+
- (MGLAnnotationView *)mapView:(MGLMapView *)mapView viewForAnnotation:(id<MGLAnnotation>)annotation
{
MGLAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:MGLTestAnnotationReuseIdentifer];
@@ -117,4 +173,9 @@ static NSString * const MGLTestAnnotationReuseIdentifer = @"MGLTestAnnotationReu
[_expectation fulfill];
}
+- (void)mapView:(MGLMapView *)mapView didSelectAnnotation:(id<MGLAnnotation>)annotation
+{
+ self.annotationSelectedCount++;
+}
+
@end
diff --git a/platform/ios/test/MGLMapViewLayoutTests.m b/platform/ios/test/MGLMapViewLayoutTests.m
index e707cfdb41..16f6cdada3 100644
--- a/platform/ios/test/MGLMapViewLayoutTests.m
+++ b/platform/ios/test/MGLMapViewLayoutTests.m
@@ -37,14 +37,15 @@
self.styleLoadingExpectation = [self expectationWithDescription:@"Map view should finish loading style."];
[self waitForExpectationsWithTimeout:1 handler:nil];
+ self.mapView.showsScale = YES;
+
//set zoom and heading so that scale bar and compass will be shown
- [self.mapView setZoomLevel:4.5 animated:NO];
+ [self.mapView setZoomLevel:10.0 animated:NO];
[self.mapView.camera setHeading:12.0];
//invoke layout
[self.superView setNeedsLayout];
[self.superView layoutIfNeeded];
-
}
- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
diff --git a/platform/ios/test/MGLMapViewScaleBarTests.m b/platform/ios/test/MGLMapViewScaleBarTests.m
new file mode 100644
index 0000000000..11d1187263
--- /dev/null
+++ b/platform/ios/test/MGLMapViewScaleBarTests.m
@@ -0,0 +1,62 @@
+#import <Mapbox/Mapbox.h>
+#import <XCTest/XCTest.h>
+
+@interface MGLMapViewScaleBarTests : XCTestCase
+
+@property (nonatomic) MGLMapView *mapView;
+
+@end
+
+@implementation MGLMapViewScaleBarTests
+
+- (void)setUp {
+ [super setUp];
+
+ [MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"];
+ NSURL *styleURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"one-liner" withExtension:@"json"];
+ self.mapView = [[MGLMapView alloc] initWithFrame:UIScreen.mainScreen.bounds styleURL:styleURL];
+}
+
+- (void)tearDown {
+ self.mapView = nil;
+
+ [super tearDown];
+}
+
+- (void)testShowsScale {
+ UIView *scaleBar = self.mapView.scaleBar;
+
+ // Scale bar should not be enabled by default.
+ XCTAssertFalse(self.mapView.showsScale);
+ XCTAssertTrue(scaleBar.hidden);
+
+ self.mapView.showsScale = YES;
+
+ XCTAssertFalse(scaleBar.hidden);
+
+ // Scale bar should not be visible at default zoom (~z0), but it should be ready.
+ XCTAssertFalse(CGRectIsEmpty(scaleBar.frame));
+ XCTAssertEqual(scaleBar.alpha, 0);
+
+ self.mapView.zoomLevel = 15;
+ XCTAssertGreaterThan(scaleBar.alpha, 0);
+}
+
+- (void)testDirectlySettingScaleBarViewHiddenProperty {
+ UIView *scaleBar = self.mapView.scaleBar;
+
+ scaleBar.hidden = NO;
+ XCTAssertFalse(scaleBar.hidden);
+
+ // Directly setting `.hidden` after the map has finished initializing will not update the scale bar.
+ XCTAssertTrue(CGRectIsEmpty(scaleBar.frame));
+
+ // ... but triggering any camera event will update it.
+ self.mapView.zoomLevel = 1;
+ XCTAssertFalse(CGRectIsEmpty(scaleBar.frame));
+ XCTAssertEqual(scaleBar.alpha, 0);
+
+ self.mapView.zoomLevel = 15;
+ XCTAssertGreaterThan(scaleBar.alpha, 0);
+}
+@end
diff --git a/platform/ios/test/MGLNSOrthographyAdditionsTests.m b/platform/ios/test/MGLNSOrthographyAdditionsTests.m
index 351fe4227e..f30553e8f6 100644
--- a/platform/ios/test/MGLNSOrthographyAdditionsTests.m
+++ b/platform/ios/test/MGLNSOrthographyAdditionsTests.m
@@ -1,7 +1,7 @@
#import <XCTest/XCTest.h>
#import "NSOrthography+MGLAdditions.h"
-#import "MGLVectorSource_Private.h"
+#import "MGLVectorTileSource_Private.h"
@interface MGLNSOrthographyAdditionsTests : XCTestCase
@@ -10,7 +10,7 @@
@implementation MGLNSOrthographyAdditionsTests
- (void)testStreetsLanguages {
- for (NSString *language in [MGLVectorSource mapboxStreetsLanguages]) {
+ for (NSString *language in [MGLVectorTileSource mapboxStreetsLanguages]) {
NSString *dominantScript = [NSOrthography mgl_dominantScriptForMapboxStreetsLanguage:language];
XCTAssertNotEqualObjects(dominantScript, @"Zyyy", @"Mapbox Streets languages should have dominant script");
}
diff --git a/platform/ios/vendor/SMCalloutView/SMCalloutView.h b/platform/ios/vendor/SMCalloutView/SMCalloutView.h
index 0b14913626..5bb73d4c84 100755
--- a/platform/ios/vendor/SMCalloutView/SMCalloutView.h
+++ b/platform/ios/vendor/SMCalloutView/SMCalloutView.h
@@ -114,6 +114,18 @@ extern NSTimeInterval const kMGLSMCalloutViewRepositionDelayForUIScrollView;
- (void)presentCalloutFromRect:(CGRect)rect inView:(UIView *)view constrainedToView:(UIView *)constrainedView animated:(BOOL)animated;
/**
+ @brief Presents a callout view by adding it to "inView" and pointing at the given rect of inView's bounds.
+
+ @discussion Constrains the callout to the rect (in the space of the given view).
+
+ @param rect @c CGRect to present the view from
+ @param view view to 'constrain' the @c constrainedView to
+ @param constrainedRect Rect to constrain the callout to
+ @param animated @c BOOL if presentation should be animated
+ */
+- (void)presentCalloutFromRect:(CGRect)rect inView:(UIView *)view constrainedToRect:(CGRect)constrainedRect animated:(BOOL)animated;
+
+/**
@brief Present a callout layer in the `layer` and pointing at the given rect of the `layer` bounds
@discussion Same as the view-based presentation, but inserts the callout into a CALayer hierarchy instead.
diff --git a/platform/ios/vendor/SMCalloutView/SMCalloutView.m b/platform/ios/vendor/SMCalloutView/SMCalloutView.m
index 9631ca0367..a0049a3e2d 100755
--- a/platform/ios/vendor/SMCalloutView/SMCalloutView.m
+++ b/platform/ios/vendor/SMCalloutView/SMCalloutView.m
@@ -247,6 +247,35 @@ NSTimeInterval const kMGLSMCalloutViewRepositionDelayForUIScrollView = 1.0/3.0;
return CGSizeMake(nudgeLeft ? nudgeLeft : nudgeRight, nudgeTop ? nudgeTop : nudgeBottom);
}
+- (UIEdgeInsets)marginInsetsHintForPresentationFromRect:(CGRect)rect {
+
+ // form our subviews based on our content set so far
+ [self rebuildSubviews];
+
+ // size the callout to fit the width constraint as best as possible
+ CGFloat height = self.calloutHeight;
+ CGSize size = [self sizeThatFits:CGSizeMake(0.0f, height)];
+
+ // Without re-jigging presentCalloutFromRect, let's just make a best-guess with what we have
+ // right now.
+ CGFloat horizontalMargin = fmaxf(0, ceilf((CALLOUT_MIN_WIDTH-rect.size.width)/2));
+
+ UIEdgeInsets insets = {
+ .top = 0.0f,
+ .right = -horizontalMargin,
+ .bottom = 0.0f,
+ .left = -horizontalMargin
+ };
+
+ if (self.permittedArrowDirection == MGLSMCalloutArrowDirectionUp)
+ insets.bottom -= size.height;
+ else
+ insets.top -= size.height;
+
+ return insets;
+}
+
+
- (void)presentCalloutFromRect:(CGRect)rect inView:(UIView *)view constrainedToView:(UIView *)constrainedView animated:(BOOL)animated {
[self presentCalloutFromRect:rect inLayer:view.layer ofView:view constrainedToLayer:constrainedView.layer animated:animated];
}
@@ -255,8 +284,18 @@ NSTimeInterval const kMGLSMCalloutViewRepositionDelayForUIScrollView = 1.0/3.0;
[self presentCalloutFromRect:rect inLayer:layer ofView:nil constrainedToLayer:constrainedLayer animated:animated];
}
-// this private method handles both CALayer and UIView parents depending on what's passed.
- (void)presentCalloutFromRect:(CGRect)rect inLayer:(CALayer *)layer ofView:(UIView *)view constrainedToLayer:(CALayer *)constrainedLayer animated:(BOOL)animated {
+ // figure out the constrained view's rect in our popup view's coordinate system
+ CGRect constrainedRect = [constrainedLayer convertRect:constrainedLayer.bounds toLayer:layer];
+ [self presentCalloutFromRect:rect inLayer:layer ofView:view constrainedToRect:constrainedRect animated:animated];
+}
+
+- (void)presentCalloutFromRect:(CGRect)rect inView:(UIView *)view constrainedToRect:(CGRect)constrainedRect animated:(BOOL)animated {
+ [self presentCalloutFromRect:rect inLayer:view.layer ofView:view constrainedToRect:constrainedRect animated:animated];
+}
+
+// this private method handles both CALayer and UIView parents depending on what's passed.
+- (void)presentCalloutFromRect:(CGRect)rect inLayer:(CALayer *)layer ofView:(UIView *)view constrainedToRect:(CGRect)constrainedRect animated:(BOOL)animated {
// Sanity check: dismiss this callout immediately if it's displayed somewhere
if (self.layer.superlayer) [self dismissCalloutAnimated:NO];
@@ -265,8 +304,6 @@ NSTimeInterval const kMGLSMCalloutViewRepositionDelayForUIScrollView = 1.0/3.0;
[self.layer removeAnimationForKey:@"present"];
[self.layer removeAnimationForKey:@"dismiss"];
- // figure out the constrained view's rect in our popup view's coordinate system
- CGRect constrainedRect = [constrainedLayer convertRect:constrainedLayer.bounds toLayer:layer];
// apply our edge constraints
constrainedRect = UIEdgeInsetsInsetRect(constrainedRect, self.constrainedInsets);
diff --git a/platform/ios/vendor/mapbox-events-ios b/platform/ios/vendor/mapbox-events-ios
new file mode 160000
+Subproject ac14fe78043eb823f14c7eefacda29aad0642c9
diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md
index 1f671cb82a..498ed3c379 100644
--- a/platform/macos/CHANGELOG.md
+++ b/platform/macos/CHANGELOG.md
@@ -1,32 +1,69 @@
# Changelog for Mapbox Maps SDK for macOS
-## master
+## 0.7.1
-### Styles and rendering
+### Style layers
-* Added support for a new layer type: `MGLHeatmapStyleLayer`, a powerful way to visualize point data distributions using heatmaps, fully customizable through runtime styling. [#11046](https://github.com/mapbox/mapbox-gl-native/pull/11046)
-* The layout and paint properties on subclasses of `MGLStyleLayer` are now of type `NSExpression` instead of `MGLStyleValue`. A new “Predicates and Expressions” guide provides an overview of the supported operators. ([#10726](https://github.com/mapbox/mapbox-gl-native/pull/10726))
+* Deprecated `+[NSExpression featurePropertiesVariableExpression]` use `+[NSExpression featureAttributesVariableExpression]` instead. ([#11748](https://github.com/mapbox/mapbox-gl-native/pull/11748))
+
+## 0.7.0 - April 19, 2018
+
+The 0.7._x_ series of releases will be the last to support macOS 10.10. The minimum macOS deployment version will increase to macOS 10.11.0 in a future release.
+
+### Packaging
+
+* Added Arabic, Danish, Hebrew, and European Portuguese localizations. ([#10967](https://github.com/mapbox/mapbox-gl-native/pull/10967), [#11136](https://github.com/mapbox/mapbox-gl-native/pull/11134), [#11695](https://github.com/mapbox/mapbox-gl-native/pull/11695))
+* Removed methods, properties, and constants that had been deprecated as of v0.6.1. ([#11205](https://github.com/mapbox/mapbox-gl-native/pull/11205))
+* Refined certain Swift interfaces by converting them from class methods to class properties. ([#11674](https://github.com/mapbox/mapbox-gl-native/pull/11674))
+
+### Style layers
+
+* The layout and paint properties on subclasses of `MGLStyleLayer` are now of type `NSExpression` instead of `MGLStyleValue`. A new “Predicates and Expressions” guide provides an overview of the supported operators, which include arithmetic and conditional operators. ([#10726](https://github.com/mapbox/mapbox-gl-native/pull/10726))
+* A style can now display a heatmap layer that visualizes a point data distribution. You can customize the appearance at runtime using the `MGLHeatmapStyleLayer` class. ([#11046](https://github.com/mapbox/mapbox-gl-native/pull/11046))
+* A style can now display a smooth hillshading layer and customize its appearance at runtime using the `MGLHillshadeStyleLayer` class. Hillshading is based on a rasterized digital elevation model supplied by the `MGLRasterDEMSource` class. ([#10642](https://github.com/mapbox/mapbox-gl-native/pull/10642))
+* You can now set the `MGLVectorStyleLayer.predicate` property to a predicate that contains arithmetic and calls to built-in `NSExpression` functions. You may need to cast a feature attribute key to `NSString` or `NSNumber` before comparing it to a string or number. ([#11587](https://github.com/mapbox/mapbox-gl-native/pull/11587))
+* Replaced the `MGLStyle.localizesLabels` property with an `-[MGLStyle localizeLabelsIntoLocale:]` method that allows you to specify the language to localize into. Note that this method does not automatically update the style when the system’s preferred language changes. Also added an `-[NSExpression(MGLAdditions) mgl_expressionLocalizedIntoLocale:]` method for localizing an individual value used with `MGLSymbolStyleLayer.text`. ([#11651](https://github.com/mapbox/mapbox-gl-native/pull/11651))
+* Fixed incorrect color calibration on macOS 10.13 High Sierra when using color-related methods of `MGLStyleLayer` subclasses, as well as when displaying an `MGLAttributionInfo`. It is no longer necessary to explicitly convert an `NSColor` to the sRGB color space before using these classes on High Sierra. ([#11391](https://github.com/mapbox/mapbox-gl-native/pull/11391))
+* The `MGLSymbolStyleLayer.textFontNames` property can now depend on a feature’s attributes. ([#10850](https://github.com/mapbox/mapbox-gl-native/pull/10850))
+* Changes to the `MGLStyleLayer.minimumZoomLevel` and `MGLStyleLayer.maximumZoomLevel` properties take effect immediately. ([#11399](https://github.com/mapbox/mapbox-gl-native/pull/11399))
+
+### Content sources
+
+* Renamed `MGLRasterSource` to `MGLRasterTileSource` and `MGLVectorSource` to `MGLVectorTileSource`. ([#11568](https://github.com/mapbox/mapbox-gl-native/pull/11568))
* Added an `MGLComputedShapeSource` class that allows applications to supply vector data to a style layer on a per-tile basis. ([#9983](https://github.com/mapbox/mapbox-gl-native/pull/9983))
-* A style can now display smooth hillshading and customize its appearance at runtime using the `MGLHillshadeStyleLayer` class. Hillshading is based on a rasterized digital elevation model supplied by the `MGLRasterDEMSource` class. ([#10642](https://github.com/mapbox/mapbox-gl-native/pull/10642))
* Properties such as `MGLSymbolStyleLayer.iconAllowsOverlap` and `MGLSymbolStyleLayer.iconIgnoresPlacement` now account for symbols in other sources. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))
+
+### Map rendering
+
* Improved the reliability of collision detection between symbols near the edges of tiles, as well as between symbols when the map is tilted. It is no longer necessary to enable `MGLSymbolStyleLayer.symbolAvoidsEdges` to prevent symbols in adjacent tiles from overlapping with each other. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))
* Symbols can fade in and out as the map pans, rotates, or tilts. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))
+* Properties such as `MGLSymbolStyleLayer.iconAllowsOverlap` and `MGLSymbolStyleLayer.iconIgnoresPlacement` now account for symbols in other sources. ([#10436](https://github.com/mapbox/mapbox-gl-native/pull/10436))
* Added the `MGLTileSourceOptionTileCoordinateBounds` option to create an `MGLTileSource` that only supplies tiles within a specific geographic bounding box. ([#11141](https://github.com/mapbox/mapbox-gl-native/pull/11141))
* Fixed an issue preventing a dynamically-added `MGLRasterStyleLayer` from drawing until the map pans. ([#10270](https://github.com/mapbox/mapbox-gl-native/pull/10270))
* Fixed an issue preventing `MGLImageSource`s from drawing on the map when the map is zoomed in and tilted. ([#10677](https://github.com/mapbox/mapbox-gl-native/pull/10677))
+* Improved the sharpness of raster tiles on Retina displays. ([#10984](https://github.com/mapbox/mapbox-gl-native/pull/10984))
+* Fixed a crash parsing a malformed style. ([#11001](https://github.com/mapbox/mapbox-gl-native/pull/11001))
+* Fixed an issue where symbols with empty labels would always be hidden. ([#11206](https://github.com/mapbox/mapbox-gl-native/pull/11206))
+* Fixed an issue where a tilted map could flicker while displaying rotating symbols. ([#11488](https://github.com/mapbox/mapbox-gl-native/pull/11488))
+* Increased the maximum width of labels by a factor of two. ([#11508](https://github.com/mapbox/mapbox-gl-native/pull/11508))
-### Other changes
+### Annotations
-* Added a Hebrew localization. ([#10967](https://github.com/mapbox/mapbox-gl-native/pull/10967))
+* Fixed an issue where tapping a group of annotations may not have selected the nearest annotation. ([#11438](https://github.com/mapbox/mapbox-gl-native/pull/11438))
+* The `MGLMapView.selectedAnnotations` property (backed by `-[MGLMapView setSelectedAnnotations:]`) now selects annotations that are off-screen. ([#9790](https://github.com/mapbox/mapbox-gl-native/issues/9790))
+* The `animated` parameter to `-[MGLMapView selectAnnotation:animated:]` now controls whether the annotation and its callout are brought on-screen. If `animated` is `NO` then the annotation is selected if offscreen, but the map is not panned. Currently only point annotations are supported.([#3249](https://github.com/mapbox/mapbox-gl-native/issues/3249))
+* Fixed a crash when rapidly adding and removing annotations. ([#11551](https://github.com/mapbox/mapbox-gl-native/issues/11551), [#11575](https://github.com/mapbox/mapbox-gl-native/issues/11575))
-### Snapshots
+### Map snapshots
* Fixed a memory leak that occurred when creating a map snapshot. ([#10585](https://github.com/mapbox/mapbox-gl-native/pull/10585))
+* Fixed an issue that caused `MGLMapSnapshotter.pointForCoordinate` to return an incorrect value. ([#11035](https://github.com/mapbox/mapbox-gl-native/pull/11035))
-## v0.6.2
+### Other changes
-* Added the `MGLTileSourceOptionTileCoordinateBounds` option to create an `MGLTileSource` that only supplies tiles within a specific geographic bounding box. ([#11141](https://github.com/mapbox/mapbox-gl-native/pull/11141))
-* Fixed an issue that caused `-[MGLMapSnapshotter pointForCoordinate:]` to return the wrong point. ([#11035](https://github.com/mapbox/mapbox-gl-native/pull/11035))
+* The `-[MGLMapView convertRect:toCoordinateBoundsFromView:]` method and the `MGLMapView.visibleCoordinateBounds` property’s getter now indicate that the coordinate bounds straddles the antimeridian by extending one side beyond ±180 degrees longitude. ([#11265](https://github.com/mapbox/mapbox-gl-native/pull/11265))
+* Feature querying results now account for the `MGLSymbolStyleLayer.circleStrokeWidth` property. ([#10897](https://github.com/mapbox/mapbox-gl-native/pull/10897))
+* Reduced offline download sizes for styles with symbol layers that render only icons, and no text. ([#11055](https://github.com/mapbox/mapbox-gl-native/pull/11055))
## v0.6.1 - January 16, 2018
diff --git a/platform/macos/DEVELOPING.md b/platform/macos/DEVELOPING.md
index 562f1291c2..bac5683266 100644
--- a/platform/macos/DEVELOPING.md
+++ b/platform/macos/DEVELOPING.md
@@ -117,6 +117,8 @@ To add an example code listing to the documentation for a class or class member:
to [MGLDocumentationExampleTests](test/MGLDocumentationExampleTests.swift).
Wrap the code you’d like to appear in the documentation within
`//#-example-code` and `//#-end-example-code` comments.
+1. If the header doesn’t already have an example code listing, add the path to
+ the header to platform/darwin/scripts/update-examples.list.
1. Insert the code listings into the headers:
```bash
diff --git a/platform/macos/Mapbox-macOS-SDK-symbols.podspec b/platform/macos/Mapbox-macOS-SDK-symbols.podspec
index f8b5397a77..597f97d03c 100644
--- a/platform/macos/Mapbox-macOS-SDK-symbols.podspec
+++ b/platform/macos/Mapbox-macOS-SDK-symbols.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |m|
- version = '0.6.1'
+ version = '0.7.0'
m.name = 'Mapbox-macOS-SDK-symbols'
m.version = "#{version}-symbols"
diff --git a/platform/macos/Mapbox-macOS-SDK.podspec b/platform/macos/Mapbox-macOS-SDK.podspec
index 6412190065..734ab19390 100644
--- a/platform/macos/Mapbox-macOS-SDK.podspec
+++ b/platform/macos/Mapbox-macOS-SDK.podspec
@@ -1,6 +1,6 @@
Pod::Spec.new do |m|
- version = '0.6.1'
+ version = '0.7.0'
m.name = 'Mapbox-macOS-SDK'
m.version = version
diff --git a/platform/macos/app/Base.lproj/MainMenu.xib b/platform/macos/app/Base.lproj/MainMenu.xib
index 72e9c5a189..8f0aeaf69c 100644
--- a/platform/macos/app/Base.lproj/MainMenu.xib
+++ b/platform/macos/app/Base.lproj/MainMenu.xib
@@ -402,16 +402,6 @@
<action selector="showStyle:" target="-1" id="NTT-Y1-EqU"/>
</connections>
</menuItem>
- <menuItem title="Traffic Day" tag="7" keyEquivalent="7" id="m9S-sv-Dch">
- <connections>
- <action selector="showStyle:" target="-1" id="lXM-BW-dDw"/>
- </connections>
- </menuItem>
- <menuItem title="Traffic Night" tag="8" keyEquivalent="8" id="yVS-VL-Xsy">
- <connections>
- <action selector="showStyle:" target="-1" id="eAD-br-oBB"/>
- </connections>
- </menuItem>
<menuItem title="Custom Style…" id="L0h-86-2cU">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
@@ -555,7 +545,13 @@
<action selector="drawAnimatedAnnotation:" target="-1" id="CYM-WB-s97"/>
</connections>
</menuItem>
- <menuItem title="Show All Annnotations" keyEquivalent="A" id="yMj-uM-8SN">
+ <menuItem title="Select an Offscreen Point Annotation" id="Xy2-Cc-RUB">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="selectOffscreenPointAnnotation:" target="-1" id="Fhm-l3-G6h"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Show All Annotations" keyEquivalent="A" id="yMj-uM-8SN">
<modifierMask key="keyEquivalentModifierMask" shift="YES" command="YES"/>
<connections>
<action selector="showAllAnnotations:" target="-1" id="ahr-OR-Em2"/>
@@ -674,7 +670,7 @@ CA
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="109" y="131" width="350" height="84"/>
- <rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="eA4-n3-qPe">
<rect key="frame" x="0.0" y="0.0" width="350" height="84"/>
<autoresizingMask key="autoresizingMask"/>
@@ -750,7 +746,7 @@ CA
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" utility="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="830" y="430" width="400" height="300"/>
- <rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="8ha-hw-zOD">
<rect key="frame" x="0.0" y="0.0" width="400" height="300"/>
<autoresizingMask key="autoresizingMask"/>
@@ -758,11 +754,11 @@ CA
<scrollView autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Q8b-0e-dLv">
<rect key="frame" x="-1" y="20" width="402" height="281"/>
<clipView key="contentView" id="J9U-Yx-o2S">
- <rect key="frame" x="1" y="0.0" width="400" height="280"/>
+ <rect key="frame" x="1" y="0.0" width="400" height="265"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" autosaveColumns="NO" headerView="MAZ-Iq-hBi" id="Ato-Vu-HYT">
- <rect key="frame" x="0.0" y="0.0" width="423" height="257"/>
+ <rect key="frame" x="0.0" y="0.0" width="423" height="242"/>
<autoresizingMask key="autoresizingMask"/>
<size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
@@ -901,7 +897,7 @@ CA
</subviews>
</clipView>
<scroller key="horizontalScroller" verticalHuggingPriority="750" horizontal="YES" id="QLr-6P-Ogs">
- <rect key="frame" x="1" y="264" width="400" height="16"/>
+ <rect key="frame" x="1" y="265" width="400" height="15"/>
<autoresizingMask key="autoresizingMask"/>
</scroller>
<scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="q0K-eE-mzL">
diff --git a/platform/macos/app/Base.lproj/MapDocument.xib b/platform/macos/app/Base.lproj/MapDocument.xib
index 0394f38533..5d0525a29d 100644
--- a/platform/macos/app/Base.lproj/MapDocument.xib
+++ b/platform/macos/app/Base.lproj/MapDocument.xib
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="12121" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="13771" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
- <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12121"/>
+ <deployment identifier="macosx"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="13771"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@@ -48,7 +49,7 @@
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES" fullSizeContentView="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="388" y="211" width="642" height="480"/>
- <rect key="screenRect" x="0.0" y="0.0" width="1680" height="1027"/>
+ <rect key="screenRect" x="0.0" y="0.0" width="1280" height="777"/>
<view key="contentView" id="TuG-C5-zLS">
<rect key="frame" x="0.0" y="0.0" width="642" height="480"/>
<autoresizingMask key="autoresizingMask"/>
@@ -70,7 +71,7 @@
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
<tableColumns>
- <tableColumn editable="NO" width="16" minWidth="16" maxWidth="1000" id="P3U-a3-c8q">
+ <tableColumn identifier="" editable="NO" width="16" minWidth="16" maxWidth="1000" id="P3U-a3-c8q">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
@@ -87,7 +88,7 @@
</binding>
</connections>
</tableColumn>
- <tableColumn editable="NO" width="141" minWidth="40" maxWidth="1000" id="BwD-ww-7uw">
+ <tableColumn identifier="" editable="NO" width="141" minWidth="40" maxWidth="1000" id="BwD-ww-7uw">
<tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
@@ -204,12 +205,6 @@
<menuItem title="Satellite Streets" tag="6" id="7ly-oA-0ND">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
- <menuItem title="Traffic Day" tag="7" id="Vz7-9Z-EFq">
- <modifierMask key="keyEquivalentModifierMask"/>
- </menuItem>
- <menuItem title="Traffic Night" tag="8" id="zh7-LM-dmF">
- <modifierMask key="keyEquivalentModifierMask"/>
- </menuItem>
</items>
</menu>
</popUpButtonCell>
diff --git a/platform/macos/app/MapDocument.m b/platform/macos/app/MapDocument.m
index 7d39f93347..9b18dbd761 100644
--- a/platform/macos/app/MapDocument.m
+++ b/platform/macos/app/MapDocument.m
@@ -6,7 +6,7 @@
#import "MGLMapsnapshotter.h"
#import "MGLStyle+MBXAdditions.h"
-#import "MGLVectorSource_Private.h"
+#import "MGLVectorTileSource_Private.h"
#import <Mapbox/Mapbox.h>
@@ -50,13 +50,13 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
return flattenedShapes;
}
-@interface MGLVectorSource (MBXAdditions)
+@interface MGLVectorTileSource (MBXAdditions)
@property (nonatomic, readonly, getter=isMapboxTerrain) BOOL mapboxTerrain;
@end
-@implementation MGLVectorSource (MBXAdditions)
+@implementation MGLVectorTileSource (MBXAdditions)
- (BOOL)isMapboxTerrain {
NSURL *url = self.configurationURL;
@@ -265,12 +265,6 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
case 6:
styleURL = [MGLStyle satelliteStreetsStyleURL];
break;
- case 7:
- styleURL = [NSURL URLWithString:@"mapbox://styles/mapbox/traffic-day-v2"];
- break;
- case 8:
- styleURL = [NSURL URLWithString:@"mapbox://styles/mapbox/traffic-night-v2"];
- break;
default:
NSAssert(NO, @"Cannot set style from control with tag %li", (long)tag);
break;
@@ -427,7 +421,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
}
- (void)updateLabels {
- self.mapView.style.localizesLabels = _isLocalizingLabels;
+ [self.mapView.style localizeLabelsIntoLocale:_isLocalizingLabels ? nil : [NSLocale localeWithLocaleIdentifier:@"mul"]];
}
- (void)applyPendingState {
@@ -647,6 +641,51 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
repeats:YES];
}
+
+- (id<MGLAnnotation>)randomOffscreenPointAnnotation {
+
+ NSPredicate *pointAnnotationPredicate = [NSPredicate predicateWithBlock:^BOOL(id _Nullable evaluatedObject, NSDictionary<NSString *,id> * _Nullable bindings) {
+ return [evaluatedObject isKindOfClass:[MGLPointAnnotation class]];
+ }];
+
+ NSArray *annotations = [self.mapView.annotations filteredArrayUsingPredicate:pointAnnotationPredicate];
+
+ if (annotations.count == 0) {
+ return nil;
+ }
+
+ // NOTE: self.mapView.visibleAnnotations occasionally returns nil - see
+ // https://github.com/mapbox/mapbox-gl-native/issues/11296
+ NSArray *visibleAnnotations = [self.mapView.visibleAnnotations filteredArrayUsingPredicate:pointAnnotationPredicate];
+
+ NSLog(@"Number of visible point annotations = %ld", visibleAnnotations.count);
+
+ if (visibleAnnotations.count == annotations.count) {
+ return nil;
+ }
+
+ NSMutableArray *invisibleAnnotations = [annotations mutableCopy];
+
+ if (visibleAnnotations.count > 0) {
+ [invisibleAnnotations removeObjectsInArray:visibleAnnotations];
+ }
+
+ // Now pick a random offscreen annotation.
+ uint32_t index = arc4random_uniform((uint32_t)invisibleAnnotations.count);
+ return invisibleAnnotations[index];
+}
+
+- (IBAction)selectOffscreenPointAnnotation:(id)sender {
+ id<MGLAnnotation> annotation = [self randomOffscreenPointAnnotation];
+ if (annotation) {
+ [self.mapView selectAnnotation:annotation];
+
+ // Alternative method to select the annotation. These two should do the same thing.
+ // self.mapView.selectedAnnotations = @[annotation];
+ NSAssert(self.mapView.selectedAnnotations.firstObject, @"The annotation was not selected");
+ }
+}
+
- (void)updateAnimatedAnnotation:(NSTimer *)timer {
DroppedPinAnnotation *annotation = timer.userInfo;
double angle = timer.fireDate.timeIntervalSinceReferenceDate;
@@ -767,8 +806,8 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
- (IBAction)enhanceTerrain:(id)sender {
// Find all the identifiers of Mapbox Terrain sources used in the style.
NSMutableSet *terrainSourceIdentifiers = [NSMutableSet set];
- for (MGLVectorSource *source in self.mapView.style.sources) {
- if (![source isKindOfClass:[MGLVectorSource class]]) {
+ for (MGLVectorTileSource *source in self.mapView.style.sources) {
+ if (![source isKindOfClass:[MGLVectorTileSource class]]) {
continue;
}
@@ -855,7 +894,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
self.mapView.style.transition = transition;
MGLStyleLayer *waterLayer = [self.mapView.style layerWithIdentifier:@"water"];
- NSExpression *colorExpression = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{
+ NSExpression *colorExpression = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{
@0.0: [NSColor redColor],
@10.0: [NSColor yellowColor],
@20.0: [NSColor blackColor],
@@ -888,7 +927,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
theaterLayer.predicate = [NSPredicate predicateWithFormat:@"maki == 'theatre'"];
theaterLayer.iconImageName = [NSExpression expressionForConstantValue:NSImageNameIChatTheaterTemplate];
theaterLayer.iconScale = [NSExpression expressionForConstantValue:@2];
- theaterLayer.iconColor = [NSExpression expressionWithFormat:@"FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)", @{
+ theaterLayer.iconColor = [NSExpression expressionWithFormat:@"mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'linear', nil, %@)", @{
@16.0: [NSColor redColor],
@18.0: [NSColor yellowColor],
@20.0: [NSColor blackColor],
@@ -981,12 +1020,6 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
case 6:
state = [styleURL isEqual:[MGLStyle satelliteStreetsStyleURL]];
break;
- case 7:
- state = [styleURL isEqual:[NSURL URLWithString:@"mapbox://styles/mapbox/traffic-day-v2"]];
- break;
- case 8:
- state = [styleURL isEqual:[NSURL URLWithString:@"mapbox://styles/mapbox/traffic-night-v2"]];
- break;
default:
return NO;
}
@@ -1034,7 +1067,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
menuItem.state = menuItem.tag == _isLocalizingLabels ? NSOnState: NSOffState;
if (menuItem.tag) {
NSLocale *locale = [NSLocale localeWithLocaleIdentifier:[NSBundle mainBundle].developmentLocalization];
- NSString *preferredLanguage = [MGLVectorSource preferredMapboxStreetsLanguage];
+ NSString *preferredLanguage = [MGLVectorTileSource preferredMapboxStreetsLanguage] ?: @"en";
menuItem.title = [locale displayNameForKey:NSLocaleIdentifier value:preferredLanguage];
}
return YES;
@@ -1123,6 +1156,9 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
if (menuItem.action == @selector(insertGraticuleLayer:)) {
return ![self.mapView.style sourceWithIdentifier:@"graticule"];
}
+ if (menuItem.action == @selector(selectOffscreenPointAnnotation:)) {
+ return YES;
+ }
if (menuItem.action == @selector(showAllAnnotations:) || menuItem.action == @selector(removeAllAnnotations:)) {
return self.mapView.annotations.count > 0;
}
@@ -1160,8 +1196,6 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
[MGLStyle darkStyleURL],
[MGLStyle satelliteStyleURL],
[MGLStyle satelliteStreetsStyleURL],
- [MGLStyle trafficDayStyleURL],
- [MGLStyle trafficNightStyleURL],
];
return [styleURLs indexOfObject:self.mapView.styleURL];
}
diff --git a/platform/macos/app/da.lproj/Localizable.strings b/platform/macos/app/da.lproj/Localizable.strings
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/platform/macos/app/da.lproj/Localizable.strings
diff --git a/platform/macos/app/pt-PT.lproj/Localizable.strings b/platform/macos/app/pt-PT.lproj/Localizable.strings
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/platform/macos/app/pt-PT.lproj/Localizable.strings
diff --git a/platform/macos/docs/guides/For Style Authors.md b/platform/macos/docs/guides/For Style Authors.md
index 636cfa7eb7..22182c7810 100644
--- a/platform/macos/docs/guides/For Style Authors.md
+++ b/platform/macos/docs/guides/For Style Authors.md
@@ -114,21 +114,22 @@ source object is a member of one of the following subclasses of `MGLSource`:
In style JSON | In the SDK
--------------|-----------
+`vector` | `MGLVectorTileSource`
+`raster` | `MGLRasterTileSource`
+`raster-dem` | `MGLRasterDEMSource`
`geojson` | `MGLShapeSource`
-`raster` | `MGLRasterSource`
-`vector` | `MGLVectorSource`
`image` | `MGLImageSource`
`canvas` and `video` sources are not supported.
### Tile sources
-Raster and vector sources may be defined in TileJSON configuration files. This
-SDK supports the properties defined in the style specification, which are a
+Raster and vector tile sources may be defined in TileJSON configuration files.
+This SDK supports the properties defined in the style specification, which are a
subset of the keys defined in version 2.1.0 of the
[TileJSON](https://github.com/mapbox/tilejson-spec/tree/master/2.1.0)
specification. As an alternative to authoring a custom TileJSON file, you may
-supply various tile source options when creating a raster or vector source.
+supply various tile source options when creating a raster or vector tile source.
These options are detailed in the `MGLTileSourceOption` documentation:
In style JSON | In TileJSON | In the SDK
@@ -304,6 +305,11 @@ iOS.
### Expression operators
+Many expression operators defined in the style specification have corresponding
+symbols to be used with the `+[NSExpression expressionWithFormat:]`,
+`+[NSExpression expressionForFunction:arguments:]`, or
+`+[NSExpression expressionForFunction:selectorName:arguments:]` method:
+
In style specification | Method, function, or predicate type | Format string syntax
-----------------------|-------------------------------------|---------------------
`array` | |
@@ -313,15 +319,15 @@ In style specification | Method, function, or predicate type | Format string syn
`string` | |
`to-boolean` | `boolValue` |
`to-color` | |
-`to-number` | `mgl_numberWithFallbackValues:` |
-`to-string` | `stringValue` |
+`to-number` | `mgl_numberWithFallbackValues:` | `CAST(zipCode, 'NSNumber')`
+`to-string` | `stringValue` | `CAST(ele, 'NSString')`
`typeof` | |
-`geometry-type` | |
-`id` | |
-`properties` | |
-`at` | |
+`geometry-type` | `NSExpression.geometryTypeVariableExpression` | `$geometryType`
+`id` | `NSExpression.featureIdentifierVariableExpression` | `$featureIdentifier`
+`properties` | `NSExpression.featureAttributesVariableExpression` | `$featureAttributes`
+`at` | `objectFrom:withIndex:` | `array[n]`
`get` | `+[NSExpression expressionForKeyPath:]` | Key path
-`has` | |
+`has` | `mgl_does:have:` | `mgl_does:have:(self, 'key')`
`length` | `count:` | `count({1, 2, 2, 3, 4, 7, 9})`
`!` | `NSNotPredicateType` | `NOT (p0 OR … OR pn)`
`!=` | `NSNotEqualToPredicateOperatorType` | `key != value`
@@ -332,14 +338,14 @@ In style specification | Method, function, or predicate type | Format string syn
`>=` | `NSGreaterThanOrEqualToPredicateOperatorType` | `key >= value`
`all` | `NSAndPredicateType` | `p0 AND … AND pn`
`any` | `NSOrPredicateType` | `p0 OR … OR pn`
-`case` | `+[NSExpression expressionForConditional:trueExpression:falseExpression:]` | `TERNARY(condition, trueExpression, falseExpression)`
-`coalesce` | |
-`match` | |
-`interpolate` | `mgl_interpolateWithCurveType:parameters:stops:` |
-`step` | `mgl_stepWithMinimum:stops:` |
-`let` | `mgl_expressionWithContext:` |
+`case` | `+[NSExpression expressionForConditional:trueExpression:falseExpression:]` or `MGL_IF` or `+[NSExpression mgl_expressionForConditional:trueExpression:falseExpresssion:]` | `TERNARY(1 = 2, YES, NO)` or `MGL_IF(1 = 2, YES, 2 = 2, YES, NO)`
+`coalesce` | `mgl_coalesce:` | `mgl_coalesce({x, y, z})`
+`match` | `MGL_MATCH` or `+[NSExpression mgl_expressionForMatchingExpression:inDictionary:defaultExpression:]` | `MGL_MATCH(x, 0, 'zero match', 1, 'one match', 'two match', 'default')`
+`interpolate` | `mgl_interpolate:withCurveType:parameters:stops:` or `+[NSExpression mgl_expressionForInterpolatingExpression:withCurveType:parameters:stops:]` |
+`step` | `mgl_step:withMinimum:stops:` or `+[NSExpression mgl_expressionForSteppingExpression:fromExpression:stops:]` |
+`let` | `mgl_expressionWithContext:` | `MGL_LET('ios', 11, 'macos', 10.13, $ios + $macos)`
`var` | `+[NSExpression expressionForVariable:]` | `$variable`
-`concat` | `stringByAppendingString:` |
+`concat` | `mgl_join:` or `-[NSExpression mgl_expressionByAppendingExpression:]` | `mgl_join({'Old', ' ', 'MacDonald'})`
`downcase` | `lowercase:` | `lowercase('DOWNTOWN')`
`upcase` | `uppercase:` | `uppercase('Elysian Fields')`
`rgb` | `+[NSColor colorWithCalibratedRed:green:blue:alpha:]` |
@@ -351,27 +357,34 @@ In style specification | Method, function, or predicate type | Format string syn
`%` | `modulus:by:` |
`^` | `raise:toPower:` | `2 ** 2`
`+` | `add:to:` | `1 + 2`
-`acos` | |
-`asin` | |
-`atan` | |
-`cos` | |
+`abs` | `abs:` | `abs(-1)`
+`acos` | `mgl_acos:` | `mgl_acos(1)`
+`asin` | `mgl_asin:` | `mgl_asin(0)`
+`atan` | `mgl_atan:` | `mgl_atan(20)`
+`ceil` | `ceiling:` | `ceiling(0.99999)`
+`cos` | `mgl_cos:` | `mgl_cos(0)`
`e` | | `%@` representing `NSNumber` containing `M_E`
+`floor` | `floor:` | `floor(-0.99999)`
`ln` | `ln:` | `ln(2)`
`ln2` | | `%@` representing `NSNumber` containing `M_LN2`
`log10` | `log:` | `log(1)`
-`log2` | |
+`log2` | `mgl_log2:` | `mgl_log2(1024)`
`max` | `max:` | `max({1, 2, 2, 3, 4, 7, 9})`
`min` | `min:` | `min({1, 2, 2, 3, 4, 7, 9})`
`pi` | | `%@` representing `NSNumber` containing `M_PI`
-`sin` | |
+`round` | `mgl_round:` | `mgl_round(1.5)`
+`sin` | `mgl_sin:` | `mgl_sin(0)`
`sqrt` | `sqrt:` | `sqrt(2)`
-`tan` | |
-`zoom` | | `$zoom`
-`heatmap-density` | | `$heatmapDensity`
+`tan` | `mgl_tan:` | `mgl_tan(0)`
+`zoom` | `NSExpression.zoomLevelVariableExpression` | `$zoom`
+`heatmap-density` | `NSExpression.heatmapDensityVariableExpression` | `$heatmapDensity`
+
+For operators that have no corresponding `NSExpression` symbol, use the
+`MGL_FUNCTION()` format string syntax.
## Filtering sources
-You can filter a shape or vector source by setting the
+You can filter a shape or vector tile source by setting the
`MGLVectorStyleLayer.predicate` property to an `NSPredicate` object. Below is a
table of style JSON operators and the corresponding operators used in the
predicate format string:
diff --git a/platform/macos/docs/guides/Info.plist Keys.md b/platform/macos/docs/guides/Info.plist Keys.md
index be6096d167..dd401d1ad3 100644
--- a/platform/macos/docs/guides/Info.plist Keys.md
+++ b/platform/macos/docs/guides/Info.plist Keys.md
@@ -8,7 +8,7 @@ Set the [Mapbox access token](https://www.mapbox.com/help/define-access-token/)
Mapbox-hosted vector tiles and styles require an API access token, which you can obtain from the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/). 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.
-As an alternative, you can use `+[MGLAccountManager setAccessToken:]` to set a token in code. See [our guide](https://www.mapbox.com/help/ios-private-access-token/) for some tips on keeping access tokens in open source code private.
+As an alternative, you can use `MGLAccountManager.accessToken` to set a token in code. See [our guide](https://www.mapbox.com/help/ios-private-access-token/) for some tips on keeping access tokens in open source code private.
## MGLMapboxAPIBaseURL
diff --git a/platform/macos/docs/guides/Migrating to Expressions.md b/platform/macos/docs/guides/Migrating to Expressions.md
new file mode 100644
index 0000000000..e8d038dbb0
--- /dev/null
+++ b/platform/macos/docs/guides/Migrating to Expressions.md
@@ -0,0 +1,267 @@
+<!--
+ This file is generated.
+ Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
+-->
+
+# Migrating from Style Functions to Expressions
+
+[Runtime Styling](runtime-styling.html) enables you to modify every aspect of the map’s appearance dynamically as a user interacts with your application. Developers can specify in advance how a layout or paint attribute will vary as the zoom level changes or how the appearance of individual features vary based on metadata provided by a content source.
+
+With Mapbox Maps SDK for macOS v0.7.0, style functions have been replaced with expressions. These provide even more tools for developers who want to style their maps dynamically. This guide outlines some tips for migrating from style functions to expressions, and offers an overview of some things that developers can do with expressions.
+
+An expression is represented at runtime by the `NSExpression` class. Expressions can be used to style paint and layout properties based on zoom level, data attributes, or a combination of the two.
+
+A constant expression can also be assigned to a style property. For example, the opacity of a fill style layer can be set to a constant value between 0 and 1.
+
+The documentation for each individual style layer property notes which non-constant expressions are enabled for that property. Style functions supported four interpolation modes: exponential, interval, categorical, and identity.
+
+This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php). Under each interpolation mode, the style function implementation will be shown, followed by the current syntax.
+
+For more information about how to work with GeoJSON data in our macOS SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide. To learn more about supported expressions, see our ["Predicates and Expressions"](predicates-and-expressions.html) guide. The "Predicates and Expressions" guide also outlines Mapbox custom functions that can be used to dynamically style a map.
+
+## Stops
+Stops are dictionary keys that are associated with layer attribute values. Constant values no longer need to be wrapped as style values when they are values in a stops dictionary.
+
+
+Style function syntax:
+
+```swift
+let stops = [
+ 0: MGLStyleValue<UIColor>(rawValue: .yellow),
+ 2.5: MGLStyleValue(rawValue: .orange),
+ 5: MGLStyleValue(rawValue: .red),
+ 7.5: MGLStyleValue(rawValue: .blue),
+ 10: MGLStyleValue(rawValue: .white),
+]
+```
+
+Current syntax:
+```swift
+let stops: [NSNumber: NSColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
+]
+```
+
+
+## Interpolation mode
+
+Style functions supported four interpolation modes: exponential/linear, interval, categorical, and identity. For more information about supported custom expressions, please see the "Predicates and Expressions" guide.
+
+### Linear
+
+`+[NSExpression(MGLAdditions) mgl_expressionForInterpolatingExpression:withCurveType:parameters:stops:]` takes the interpolation type as a parameter. If you previously used the default interpolation base, use the curve type `MGLExpressionInterpolationMode.linear`. See the [`mgl_interpolate:withCurveType:parameters:stops:`](predicates-and-expressions.html#code-mgl_interpolate-withcurvetype-parameters-stops-code) documentation for more details.
+
+The stops dictionary below, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value.
+
+Style function syntax:
+
+```swift
+let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
+let symbolSource = MGLSource(identifier: "source")
+let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbolSource)
+
+let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil)
+mapView.style?.addSource(source)
+
+let stops = [
+ 0: MGLStyleValue<UIColor>(rawValue: .yellow),
+ 2.5: MGLStyleValue(rawValue: .orange),
+ 5: MGLStyleValue(rawValue: .red),
+ 7.5: MGLStyleValue(rawValue: .blue),
+ 10: MGLStyleValue(rawValue: .white),
+]
+
+let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
+layer.circleColor = MGLStyleValue(interpolationMode: .exponential,
+ sourceStops: stops,
+ attributeName: "mag",
+ options: [.defaultValue: MGLStyleValue<UIColor>(rawValue: .green)])
+layer.circleRadius = MGLStyleValue(rawValue: 10)
+mapView.style?.insertLayer(layer, below: symbolLayer)
+```
+
+Current syntax:
+
+```swift
+let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
+let symbolSource = MGLSource(identifier: "source")
+let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbolSource)
+
+let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil)
+mapView.style?.addSource(source)
+
+let stops: [NSNumber: NSColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
+]
+
+let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
+layer.circleColor = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:(mag, 'linear', nil, %@)",
+ stops)
+layer.circleRadius = NSExpression(forConstantValue: 10)
+mapView.style?.insertLayer(layer, below: symbolLayer)
+```
+
+### Exponential
+
+If you previously used an interpolation base greater than `0` (other than `1`), you can use `MGLExpressionInterpolationMode.exponential` as the curve type for `+[NSExpression(MGLAdditions) mgl_expressionForInterpolatingExpression:withCurveType:parameters:stops:]` or `'exponential'` as the curve type for [`mgl_interpolate:withCurveType:parameters:stops:`](predicates-and-expressions.html#code-mgl_interpolate-withcurvetype-parameters-stops-code). The `parameters` argument takes that interpolation base. This interpolates between values exponentially, creating an accelerated ramp effect.
+
+Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom. In order to convert camera style functions, use `$zoomLevel` or `MGL_FUNCTION('zoomLevel')` as the attribute key.
+
+<img src="img/data-driven-styling/exponential-function.png" height=344/>
+<img src="img/data-driven-styling/exponential-function-1.png" height=344/>
+
+The example below increases a layer’s `circleRadius` exponentially based on a map’s zoom level. The interpolation base is `1.5`.
+
+Style function syntax:
+
+```swift
+let stops = [
+ 12: MGLStyleValue<NSNumber>(rawValue: 0.5),
+ 14: MGLStyleValue(rawValue: 2),
+ 18: MGLStyleValue(rawValue: 18),
+]
+
+layer.circleRadius = MGLStyleValue(interpolationMode: .exponential,
+ cameraStops: stops,
+ options: [.interpolationBase: 1.5])
+```
+
+Current syntax:
+
+```swift
+let stops = [
+ 12: 0.5,
+ 14: 2,
+ 18: 18,
+]
+
+layer.circleRadius = NSExpression(format: "mgl_interpolate:withCurveType:parameters:stops:($zoomLevel, 'exponential', 1.5, %@)",
+ stops)
+```
+
+### Interval
+
+Steps, or intervals, create a range using the keys from the stops dictionary. The range is from the given key to just less than the next key. The attribute values that fall into that range are then styled using the layout or paint value assigned to that key. You can use the `+[NSExpression(MGLAdditions) mgl_expressionForSteppingExpression:fromExpression:stops:]` method or the custom function [`mgl_step:from:stops:`](predicates-and-expressions.html#code-mgl_step-from-stops-code) for cases where you previously used interval interpolation mode. The first parameter takes the feature attribute name and the second parameter (`from:`) optionally takes the default or fallback value for that function. The final parameter takes a stops dictionary as an argument.
+
+When we use the stops dictionary given above with an `'mgl_step:from:stops:'`, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on.
+
+Style function syntax:
+
+```swift
+let stops = [
+ 0: MGLStyleValue<UIColor>(rawValue: .yellow),
+ 2.5: MGLStyleValue(rawValue: .orange),
+ 5: MGLStyleValue(rawValue: .red),
+ 7.5: MGLStyleValue(rawValue: .blue),
+ 10: MGLStyleValue(rawValue: .white),
+]
+
+layer.circleColor = MGLStyleValue(interpolationMode: .interval,
+ sourceStops: stops,
+ attributeName: "mag",
+ options: [.defaultValue: MGLStyleValue<UIColor>(rawValue: .green)])
+````
+
+Current syntax:
+
+```swift
+let stops: [NSNumber: NSColor] = [
+ 0: .yellow,
+ 2.5: .orange,
+ 5: .red,
+ 7.5: .blue,
+ 10: .white,
+]
+
+layer.circleColor = NSExpression(format: "mgl_step:from:stops:(mag, %@, %@)",
+ NSColor.green, stops)
+```
+
+### Categorical
+
+Categorical interpolation mode took a stops dictionary. If the value for a specified feature attribute name matched one in that stops dictionary, the style value for that attribute value would be used. Categorical style functions can now be replaced with `MGL_MATCH`.
+
+`MGL_MATCH` takes an initial condition, which in this case is an attribute key. This is followed by possible matches for that key and the value to assign to the layer property if there is a match. The final argument can be a default style value that is to be used if none of the specified values match.
+
+There are three main types of events in the USGS dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of blue to catch any events that do not fall into any of those categories.
+
+Style function syntax:
+
+```swift
+let categoricalStops = [
+ "earthquake": MGLStyleValue<UIColor>(rawValue: .orange),
+ "explosion": MGLStyleValue(rawValue: .red),
+ "quarry blast": MGLStyleValue(rawValue: .yellow),
+]
+
+layer.circleColor = MGLStyleValue(interpolationMode: .categorical,
+ sourceStops: categoricalStops,
+ attributeName: "type",
+ options: [.defaultValue: MGLStyleValue<UIColor>(rawValue: .blue)])
+```
+
+Current syntax:
+```swift
+let defaultColor = NSColor.blue
+layer.circleColor = NSExpression(
+format: "MGL_MATCH(type, 'earthquake', %@, 'explosion', %@, 'quarry blast', %@, %@)",
+ NSColor.orange, NSColor.red, NSColor.yellow, defaultColor)
+```
+
+If your use case does not require a default value, you can either apply a predicate to your layer prior to styling it, or use the format string `"valueForKeyPath:"`.
+
+### Identity
+
+Identity interpolation mode used the attribute’s value as the style layer property value. In this example, you might set the `circleRadius` to the earthquake’s magnitude. In order to use a feature attribute value to style a layer property, set the property value to `[NSExpression expressionForKeyPath:]`, which take the feature attribute name as an argument.
+
+Style function syntax:
+
+```swift
+layer.circleRadius = MGLStyleValue(interpolationMode: .identity,
+ sourceStops: nil,
+ attributeName: "mag",
+ options: [.defaultValue: MGLStyleValue<NSNumber>(rawValue: 0)])
+```
+
+Current syntax:
+```swift
+layer.circleRadius = NSExpression(forKeyPath: "mag")
+```
+
+![identity mode](img/data-driven-styling/identity.png)
+
+Some built-in functions can be applied to attribute values to style layer property values. To set the circle radius to three times the earthquake’s magnitude, create a `multiply:by:` function that takes the attribute value and the multiplier as arguments, or use a format string.
+
+```swift
+layer.circleRadius = NSExpression(forFunction: "multiply:by:", arguments: [NSExpression(forKeyPath: "mag"), 3])
+```
+
+![multiply magnitude](img/data-driven-styling/multiply.png)
+
+You can also cast attribute values in order to use them. One example is to cast an integer as an `NSString` and use it as a text value.
+
+```swift
+let magnitudeLayer = MGLSymbolStyleLayer(identifier: "mag-layer", source: source)
+magnitudeLayer.text = NSExpression(format: "CAST(mag, 'NSString')")
+mapView.style?.addLayer(magnitudeLayer)
+```
+
+![cast a value](img/data-driven-styling/cast.png)
+
+### Constant Values
+
+For constant values that do not necessarily change based on camera or attribute values, use `[NSExpression expressionForConstantValue:]` (previously `[MGLStyleValue valueWithRawValue:]`).
+
+## Resources
+
+* [USGS Earthquake Feed](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php)
+* [For Style Authors](for-style-authors.html)
+* [Predicates and Expressions](predicates-and-expressions.html)
diff --git a/platform/macos/docs/guides/Tile URL Templates.md b/platform/macos/docs/guides/Tile URL Templates.md
index 01672c6686..e71bcab0a4 100644
--- a/platform/macos/docs/guides/Tile URL Templates.md
+++ b/platform/macos/docs/guides/Tile URL Templates.md
@@ -4,12 +4,12 @@
-->
# Tile URL Templates
-`MGLTileSource` objects, specifically `MGLRasterSource` and `MGLVectorSource`
-objects, can be created using an initializer that accepts an array of tile URL
-templates. Tile URL templates are strings that specify the URLs of the vector
-tiles or raster tile images to load. A template resembles an absolute URL, but
-with any number of placeholder strings that the source evaluates based on the
-tile it needs to load. For example:
+`MGLTileSource` objects, specifically `MGLRasterTileSource` and
+`MGLVectorTileSource` objects, can be created using an initializer that accepts
+an array of tile URL templates. Tile URL templates are strings that specify the
+URLs of the vector tiles or raster tile images to load. A template resembles an
+absolute URL, but with any number of placeholder strings that the source
+evaluates based on the tile it needs to load. For example:
* `http://www.example.com/tiles/{z}/{x}/{y}.pbf` could be
evaluated as `http://www.example.com/tiles/14/6/9.pbf`.
@@ -56,7 +56,7 @@ all of which are optional:
<td>The tile’s zoom level. At zoom level 0, each tile covers the entire
world map; at zoom level 1, it covers ¼ of the world; at zoom level 2,
<sup>1</sup>⁄<sub>16</sub> of the world, and so on. For tiles loaded by
- a <code>MGLRasterSource</code> object, whether the tile zoom level
+ a <code>MGLRasterTileSource</code> object, whether the tile zoom level
matches the map’s current zoom level depends on the value of the
source’s tile size as specified in the
<code>MGLTileSourceOptionTileSize</code> key of the <code>options</code>
diff --git a/platform/macos/docs/guides/Using Style Functions at Runtime.md b/platform/macos/docs/guides/Using Style Functions at Runtime.md
deleted file mode 100644
index 4e854aaaa0..0000000000
--- a/platform/macos/docs/guides/Using Style Functions at Runtime.md
+++ /dev/null
@@ -1,154 +0,0 @@
-<!--
- This file is generated.
- Edit platform/darwin/scripts/generate-style-code.js, then run `make darwin-style-code`.
--->
-
-# Using Style Functions at Runtime
-
-[Runtime Styling](runtime-styling.html) enables you to modify every aspect of the map’s appearance dynamically as a user interacts with your application. Much of the runtime styling API allows you to specify _style functions_ instead of constant values. A style function allows you to specify in advance how a layout or paint attribute will vary as the zoom level changes or how the appearance of individual features vary based on metadata provided by a content source.
-
-Style functions spare you the inconvenience of manually calculating intermediate values between different zoom levels or creating a multitude of style layers to handle homogeneous features in the map content. For example, if your content source indicates the prices of hotels in an area, you can color-code the hotels by price, relying on a style function to smoothly interpolate among desired colors without having to specify the color for each exact price.
-
-_Data-driven styling_ specifically refers to the use of style functions to vary the map’s appearance based on data in a content source.
-
-You can also specify style functions in a style JSON file, to be applied automatically when the map loads. See the [Mapbox Style Specification](https://www.mapbox.com/mapbox-gl-js/style-spec/#types-function) for details.
-
-![available bikes](img/data-driven-styling/citibikes.png) ![subway lines](img/data-driven-styling/polylineExample.png)
-
-This guide uses earthquake data from the [U.S. Geological Survey](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php) and data-driven styling to style a map based on attributes. For more information about how to work with GeoJSON data in our iOS SDK, please see our [working with GeoJSON data](working-with-geojson-data.html) guide.
-
-A style function is represented at runtime by the `MGLStyleFunction` class. There are three subclasses of `MGLStyleFunction`:
-
-* `MGLCameraStyleFunction` is a style value that changes with zoom level. For example, you can make the radius of a circle increase according to zoom level.
-* `MGLSourceStyleFunction` is a style value that changes with the attributes of a feature. For example, you can adjust the radius of a circle based on the magnitude of an earthquake.
-* `MGLCompositeStyleFunction` is a style value that changes with both zoom level and attribute values. For example, you can add a circle layer where each circle has a radius based on both zoom level and the magnitude of an earthquake.
-
-The documentation for each individual style layer property notes which style functions are enabled for that property.
-
-## Stops
-
-Stops are dictionary keys that are associated with layer attribute values. With feature attribute values as stops, you can use a dictionary with a zoom level for a key and an expression or constant value for the value. For example, you can use a stop dictionary with the zoom levels 0, 10, and 20 as keys and the colors yellow, orange, and red as the values. Alternatively, attribute values can be the keys.
-
-```swift
-let stops: [Float: NSColor] = [
- 0: .yellow,
- 2.5: .orange,
- 5: .red,
- 7.5: .blue,
- 10: .white,
-]
-```
-
-## Interpolation mode
-
-The effect a key has on the style value is determined by the interpolation mode. There are four interpolation modes that can be used with a source style function: exponential, interval, categorical, and identity. You can also use exponential and interval interpolation modes with a camera style function.
-
-### Linear
-
-`MGLInterpolationModeExponential` interpolates linearly or exponentially between style function stop values. By default, the `MGLStyleFunction` options parameter `MGLStyleFunctionOptionInterpolationBase` equals `1`, which represents linear interpolation and doesn’t need to be included in the options dictionary.
-
-The stops dictionary below, for example, shows colors that continuously shift from yellow to orange to red to blue to white based on the attribute value.
-
-```swift
-let url = URL(string: "https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/all_week.geojson")!
-let symbolSource = MGLSource(identifier: "source")
-let symbolLayer = MGLSymbolStyleLayer(identifier: "place-city-sm", source: symbolSource)
-
-let source = MGLShapeSource(identifier: "earthquakes", url: url, options: nil)
-mapView.style?.addSource(source)
-
-let stops: [Float: NSColor] = [
- 0: .yellow,
- 2.5: .orange,
- 5: .red,
- 7.5: .blue,
- 10: .white,
-]
-
-let layer = MGLCircleStyleLayer(identifier: "circles", source: source)
-layer.circleColor = NSExpression(format: "FUNCTION(mag, 'mgl_interpolateWithCurveType:parameters:stops:', 'linear', nil, %@)",
- stops)
-layer.circleRadius = NSExpression(forConstantValue: 10)
-mapView.style?.insertLayer(layer, below: symbolLayer)
-```
-
-![exponential mode](img/data-driven-styling/exponential.png)
-
-### Exponential
-
-By combining `MGLInterpolationModeExponential` with an `MGLStyleFunctionOptionInterpolationBase` greater than `0` (other than `1`), you can interpolate between values exponentially, create an accelerated ramp effect.
-
-Here’s a visualization from Mapbox Studio (see [Working with Mapbox Studio](working-with-mapbox-studio.html)) comparing interpolation base values of `1.5` and `0.5` based on zoom.
-
-<img src="img/data-driven-styling/exponential-function.png" height=344/>
-<img src="img/data-driven-styling/exponential-function-1.png" height=344/>
-
-The example below increases a layer’s `circleRadius` exponentially based on a map’s zoom level. The `MGLStyleFunctionOptionInterpolationBase` is `1.5`.
-
-```swift
-let stops = [
- 12: 0.5,
- 14: 2,
- 18: 18,
-]
-
-layer.circleRadius = NSExpression(format: "FUNCTION($zoomLevel, 'mgl_interpolateWithCurveType:parameters:stops:', 'exponential', 1.5, %@)",
- stops)
-```
-
-### Interval
-
-`MGLInterpolationModeInterval` creates a range using the keys from the stops dictionary. The range is from the given key to just less than the next key. The attribute values that fall into that range are then styled using the style value assigned to that key.
-
-When we use the stops dictionary given above with an interval interpolation mode, we create ranges where earthquakes with a magnitude of 0 to just less than 2.5 would be yellow, 2.5 to just less than 5 would be orange, and so on.
-
-```swift
-let stops: [Float: NSColor] = [
- 0: .yellow,
- 2.5: .orange,
- 5: .red,
- 7.5: .blue,
- 10: .white,
-]
-
-layer.circleColor = NSExpression(format: "FUNCTION(mag, 'mgl_stepWithMinimum:stops:', %@, %@)",
- NSColor.green, stops)
-```
-
-![interval mode](img/data-driven-styling/interval.png)
-
-### Categorical
-
-At each stop, `MGLInterpolationModeCategorical` produces an output value equal to the function input. We’re going to use a different stops dictionary than we did for the previous two modes.
-
-There are three main types of events in the dataset: earthquakes, explosions, and quarry blasts. In this case, the color of the circle layer will be determined by the type of event, with a default value of blue to catch any events that do not fall into any of those categories.
-
-```swift
-let colors: [String: NSColor] = [
- "earthquake": .orange,
- "explosion": .red,
- "quarry blast": .yellow,
-]
-let defaultColor = NSColor.blue
-
-layer.circleColor = NSExpression(
- format: "TERNARY(FUNCTION(%@, 'valueForKeyPath:', type) != nil, FUNCTION(%@, 'valueForKeyPath:', type), %@)",
- colors, colors, defaultColor)
-```
-
-![categorical mode](img/data-driven-styling/categorical1.png) ![categorical mode](img/data-driven-styling/categorical2.png)
-
-### Identity
-
-`MGLInterpolationModeIdentity` uses the attribute’s value as the style value. For example, you can set the `circleRadius` to the earthquake’s magnitude. Since the attribute value itself will be used as the style value, `sourceStops` should be set to `nil`.
-
-```swift
-layer.circleRadius = NSExpression(forKeyPath: "mag")
-```
-
-![identity mode](img/data-driven-styling/identity.png)
-
-##Resources
-
-* [USGS](https://earthquake.usgs.gov/earthquakes/feed/v1.0/geojson.php)
-* [For Style Authors](for-style-authors.html)
diff --git a/platform/macos/docs/img/screenshot.jpg b/platform/macos/docs/img/screenshot.jpg
index a8c64a69fe..4af752b299 100644
--- a/platform/macos/docs/img/screenshot.jpg
+++ b/platform/macos/docs/img/screenshot.jpg
Binary files differ
diff --git a/platform/macos/jazzy.yml b/platform/macos/jazzy.yml
index b4dccb620f..e1053324fb 100644
--- a/platform/macos/jazzy.yml
+++ b/platform/macos/jazzy.yml
@@ -20,7 +20,7 @@ custom_categories:
- Working with GeoJSON Data
- Predicates and Expressions
- For Style Authors
- - Using Style Functions at Runtime
+ - Style Layers Using Expressions
- Tile URL Templates
- Info.plist Keys
- name: Maps
@@ -63,13 +63,13 @@ custom_categories:
- name: Content Sources
children:
- MGLSource
- - MGLTileSource
- - MGLAbstractShapeSource
- MGLShapeSource
- MGLComputedShapeSource
- - MGLRasterSource
+ - MGLTileSource
+ - MGLRasterTileSource
- MGLRasterDEMSource
- - MGLVectorSource
+ - MGLVectorTileSource
+ - MGLImageSource
- name: Style Layers
children:
- MGLStyleLayer
diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj
index 4327670911..d49e5e6f06 100644
--- a/platform/macos/macos.xcodeproj/project.pbxproj
+++ b/platform/macos/macos.xcodeproj/project.pbxproj
@@ -11,9 +11,7 @@
07A019EF1ED665CD00ACD43E /* MGLImageSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07A019EC1ED662D800ACD43E /* MGLImageSource.mm */; };
07A240941F675674002C8210 /* MGLComputedShapeSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 07A240921F67566F002C8210 /* MGLComputedShapeSourceTests.m */; };
07BA4CAC1EE21887004528F5 /* MGLImageSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 07BA4CAB1EE21887004528F5 /* MGLImageSourceTests.m */; };
- 07D9474B1F6743F000E37934 /* MGLAbstractShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07D947491F6741F500E37934 /* MGLAbstractShapeSource.mm */; };
- 07D9474C1F67441500E37934 /* MGLAbstractShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D947481F6741F500E37934 /* MGLAbstractShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 07D9474D1F67441B00E37934 /* MGLAbstractShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D947471F6741F500E37934 /* MGLAbstractShapeSource_Private.h */; };
+ 07D9474D1F67441B00E37934 /* MGLComputedShapeSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 07D947471F6741F500E37934 /* MGLComputedShapeSource_Private.h */; };
07F8E2F71F674C8800F794BB /* MGLComputedShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 07F8E2F41F674C8000F794BB /* MGLComputedShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
07F8E2F81F674C9000F794BB /* MGLComputedShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 07F8E2F51F674C8000F794BB /* MGLComputedShapeSource.mm */; };
170A82BF201BDD1B00943087 /* MGLHeatmapStyleLayerTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 170A82BE201BDD1B00943087 /* MGLHeatmapStyleLayerTests.mm */; };
@@ -32,8 +30,8 @@
352742781D4C220900A1ECE6 /* MGLStyleValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 352742771D4C220900A1ECE6 /* MGLStyleValue.h */; settings = {ATTRIBUTES = (Public, ); }; };
352742811D4C243B00A1ECE6 /* MGLSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 3527427F1D4C243B00A1ECE6 /* MGLSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
352742821D4C243B00A1ECE6 /* MGLSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 352742801D4C243B00A1ECE6 /* MGLSource.mm */; };
- 352742851D4C244700A1ECE6 /* MGLRasterSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 352742831D4C244700A1ECE6 /* MGLRasterSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
- 352742861D4C244700A1ECE6 /* MGLRasterSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 352742841D4C244700A1ECE6 /* MGLRasterSource.mm */; };
+ 352742851D4C244700A1ECE6 /* MGLRasterTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 352742831D4C244700A1ECE6 /* MGLRasterTileSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 352742861D4C244700A1ECE6 /* MGLRasterTileSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 352742841D4C244700A1ECE6 /* MGLRasterTileSource.mm */; };
352742891D4C245800A1ECE6 /* MGLShapeSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 352742871D4C245800A1ECE6 /* MGLShapeSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
3527428A1D4C245800A1ECE6 /* MGLShapeSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = 352742881D4C245800A1ECE6 /* MGLShapeSource.mm */; };
3527428D1D4C24AB00A1ECE6 /* MGLCircleStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = 3527428B1D4C24AB00A1ECE6 /* MGLCircleStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -123,8 +121,8 @@
DA6408D81DA4E5DA00908C90 /* MGLVectorStyleLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = DA6408D61DA4E5DA00908C90 /* MGLVectorStyleLayer.m */; };
DA7262071DEEDD460043BB89 /* MGLOpenGLStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA7262051DEEDD460043BB89 /* MGLOpenGLStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA7262081DEEDD460043BB89 /* MGLOpenGLStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA7262061DEEDD460043BB89 /* MGLOpenGLStyleLayer.mm */; };
- DA7DC9811DED5F5C0027472F /* MGLVectorSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA7DC9801DED5F5C0027472F /* MGLVectorSource_Private.h */; };
- DA7DC9831DED647F0027472F /* MGLRasterSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA7DC9821DED647F0027472F /* MGLRasterSource_Private.h */; };
+ DA7DC9811DED5F5C0027472F /* MGLVectorTileSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA7DC9801DED5F5C0027472F /* MGLVectorTileSource_Private.h */; };
+ DA7DC9831DED647F0027472F /* MGLRasterTileSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA7DC9821DED647F0027472F /* MGLRasterTileSource_Private.h */; };
DA839E971CC2E3400062CAFB /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = DA839E961CC2E3400062CAFB /* AppDelegate.m */; };
DA839E9A1CC2E3400062CAFB /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DA839E991CC2E3400062CAFB /* main.m */; };
DA839E9D1CC2E3400062CAFB /* MapDocument.m in Sources */ = {isa = PBXBuildFile; fileRef = DA839E9C1CC2E3400062CAFB /* MapDocument.m */; };
@@ -154,8 +152,8 @@
DA8F25901D51CA600010E6B5 /* MGLRasterStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA8F258E1D51CA600010E6B5 /* MGLRasterStyleLayer.mm */; };
DA8F25931D51CA750010E6B5 /* MGLSymbolStyleLayer.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8F25911D51CA750010E6B5 /* MGLSymbolStyleLayer.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA8F25941D51CA750010E6B5 /* MGLSymbolStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA8F25921D51CA750010E6B5 /* MGLSymbolStyleLayer.mm */; };
- DA8F25971D51CAC70010E6B5 /* MGLVectorSource.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8F25951D51CAC70010E6B5 /* MGLVectorSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
- DA8F25981D51CAC70010E6B5 /* MGLVectorSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA8F25961D51CAC70010E6B5 /* MGLVectorSource.mm */; };
+ DA8F25971D51CAC70010E6B5 /* MGLVectorTileSource.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8F25951D51CAC70010E6B5 /* MGLVectorTileSource.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ DA8F25981D51CAC70010E6B5 /* MGLVectorTileSource.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA8F25961D51CAC70010E6B5 /* MGLVectorTileSource.mm */; };
DA8F259A1D51CAD00010E6B5 /* MGLSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8F25991D51CAD00010E6B5 /* MGLSource_Private.h */; };
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 */; };
@@ -298,9 +296,7 @@
07A019EC1ED662D800ACD43E /* MGLImageSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLImageSource.mm; sourceTree = "<group>"; };
07A240921F67566F002C8210 /* MGLComputedShapeSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLComputedShapeSourceTests.m; sourceTree = "<group>"; };
07BA4CAB1EE21887004528F5 /* MGLImageSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLImageSourceTests.m; sourceTree = "<group>"; };
- 07D947471F6741F500E37934 /* MGLAbstractShapeSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAbstractShapeSource_Private.h; sourceTree = "<group>"; };
- 07D947481F6741F500E37934 /* MGLAbstractShapeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAbstractShapeSource.h; sourceTree = "<group>"; };
- 07D947491F6741F500E37934 /* MGLAbstractShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAbstractShapeSource.mm; sourceTree = "<group>"; };
+ 07D947471F6741F500E37934 /* MGLComputedShapeSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLComputedShapeSource_Private.h; sourceTree = "<group>"; };
07F8E2F41F674C8000F794BB /* MGLComputedShapeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLComputedShapeSource.h; sourceTree = "<group>"; };
07F8E2F51F674C8000F794BB /* MGLComputedShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLComputedShapeSource.mm; sourceTree = "<group>"; };
170A82BE201BDD1B00943087 /* MGLHeatmapStyleLayerTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLHeatmapStyleLayerTests.mm; sourceTree = "<group>"; };
@@ -319,8 +315,8 @@
352742771D4C220900A1ECE6 /* MGLStyleValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyleValue.h; sourceTree = "<group>"; };
3527427F1D4C243B00A1ECE6 /* MGLSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLSource.h; sourceTree = "<group>"; };
352742801D4C243B00A1ECE6 /* MGLSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLSource.mm; sourceTree = "<group>"; };
- 352742831D4C244700A1ECE6 /* MGLRasterSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLRasterSource.h; sourceTree = "<group>"; };
- 352742841D4C244700A1ECE6 /* MGLRasterSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLRasterSource.mm; sourceTree = "<group>"; };
+ 352742831D4C244700A1ECE6 /* MGLRasterTileSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLRasterTileSource.h; sourceTree = "<group>"; };
+ 352742841D4C244700A1ECE6 /* MGLRasterTileSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLRasterTileSource.mm; sourceTree = "<group>"; };
352742871D4C245800A1ECE6 /* MGLShapeSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeSource.h; sourceTree = "<group>"; };
352742881D4C245800A1ECE6 /* MGLShapeSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLShapeSource.mm; sourceTree = "<group>"; };
3527428B1D4C24AB00A1ECE6 /* MGLCircleStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCircleStyleLayer.h; sourceTree = "<group>"; };
@@ -454,8 +450,8 @@
DA737AE31E5915A500AD2CDE /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = pl; path = pl.lproj/Foundation.stringsdict; sourceTree = "<group>"; };
DA737AE41E5915B000AD2CDE /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = pl.lproj/Localizable.strings; sourceTree = "<group>"; };
DA737AEC1E59180E00AD2CDE /* uk */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = uk; path = uk.lproj/Localizable.strings; sourceTree = "<group>"; };
- DA7DC9801DED5F5C0027472F /* MGLVectorSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorSource_Private.h; sourceTree = "<group>"; };
- DA7DC9821DED647F0027472F /* MGLRasterSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLRasterSource_Private.h; sourceTree = "<group>"; };
+ DA7DC9801DED5F5C0027472F /* MGLVectorTileSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorTileSource_Private.h; sourceTree = "<group>"; };
+ DA7DC9821DED647F0027472F /* MGLRasterTileSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLRasterTileSource_Private.h; sourceTree = "<group>"; };
DA80E95D1FE84A300065FC9B /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = "<group>"; };
DA80E95F1FE84A540065FC9B /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = ar; path = ar.lproj/Foundation.stringsdict; sourceTree = "<group>"; };
DA839E921CC2E3400062CAFB /* Mapbox GL.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Mapbox GL.app"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -492,8 +488,8 @@
DA8F258E1D51CA600010E6B5 /* MGLRasterStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLRasterStyleLayer.mm; sourceTree = "<group>"; };
DA8F25911D51CA750010E6B5 /* MGLSymbolStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLSymbolStyleLayer.h; sourceTree = "<group>"; };
DA8F25921D51CA750010E6B5 /* MGLSymbolStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLSymbolStyleLayer.mm; sourceTree = "<group>"; };
- DA8F25951D51CAC70010E6B5 /* MGLVectorSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorSource.h; sourceTree = "<group>"; };
- DA8F25961D51CAC70010E6B5 /* MGLVectorSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLVectorSource.mm; sourceTree = "<group>"; };
+ DA8F25951D51CAC70010E6B5 /* MGLVectorTileSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLVectorTileSource.h; sourceTree = "<group>"; };
+ DA8F25961D51CAC70010E6B5 /* MGLVectorTileSource.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLVectorTileSource.mm; sourceTree = "<group>"; };
DA8F25991D51CAD00010E6B5 /* MGLSource_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLSource_Private.h; sourceTree = "<group>"; };
DA8F259B1D51CB000010E6B5 /* MGLStyleValue_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyleValue_Private.h; sourceTree = "<group>"; };
DA8F25A61D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSValue+MGLStyleAttributeAdditions.h"; sourceTree = "<group>"; };
@@ -501,6 +497,10 @@
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>"; };
+ DA934097208562590059919A /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = "<group>"; };
+ DA934098208562870059919A /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "pt-PT"; path = "pt-PT.lproj/Foundation.stringsdict"; sourceTree = "<group>"; };
+ DA9340992085629E0059919A /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/Localizable.strings"; sourceTree = "<group>"; };
+ DA9340A0208565870059919A /* ar */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ar; path = ar.lproj/Localizable.strings; sourceTree = "<group>"; };
DA9C01301E4C7B9300C4742A /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = "pt-BR"; path = "pt-BR.lproj/Foundation.stringsdict"; sourceTree = "<group>"; };
DA9C01311E4C7B9F00C4742A /* pt-BR */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-BR"; path = "pt-BR.lproj/Localizable.strings"; sourceTree = "<group>"; };
DAA32CA61E4C4849006F8D24 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = "<group>"; };
@@ -536,6 +536,10 @@
DACFE7971F66EA0C00630DA8 /* vi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = vi; path = vi.lproj/Foundation.stringsdict; sourceTree = "<group>"; };
DAD165721CF4CD7A001FF4B9 /* MGLShapeCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLShapeCollection.h; sourceTree = "<group>"; };
DAD165731CF4CD7A001FF4B9 /* MGLShapeCollection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLShapeCollection.mm; sourceTree = "<group>"; };
+ DAD88E03202ACF5900AAA536 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = "<group>"; };
+ DAD88E04202ACF7C00AAA536 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Foundation.strings; sourceTree = "<group>"; };
+ DAD88E05202ACF8200AAA536 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.stringsdict; name = da; path = da.lproj/Foundation.stringsdict; sourceTree = "<group>"; };
+ DAD88E06202ACF9200AAA536 /* da */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = da; path = da.lproj/Localizable.strings; sourceTree = "<group>"; };
DAE6C2E11CC304F900DB3429 /* Credits.rtf */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.rtf; path = Credits.rtf; sourceTree = "<group>"; };
DAE6C2E31CC3050F00DB3429 /* DroppedPinAnnotation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DroppedPinAnnotation.h; sourceTree = "<group>"; };
DAE6C2E41CC3050F00DB3429 /* DroppedPinAnnotation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DroppedPinAnnotation.m; sourceTree = "<group>"; };
@@ -715,14 +719,12 @@
3527427E1D4C242B00A1ECE6 /* Sources */ = {
isa = PBXGroup;
children = (
- 07D947481F6741F500E37934 /* MGLAbstractShapeSource.h */,
- 07D947471F6741F500E37934 /* MGLAbstractShapeSource_Private.h */,
- 07D947491F6741F500E37934 /* MGLAbstractShapeSource.mm */,
07F8E2F41F674C8000F794BB /* MGLComputedShapeSource.h */,
+ 07D947471F6741F500E37934 /* MGLComputedShapeSource_Private.h */,
07F8E2F51F674C8000F794BB /* MGLComputedShapeSource.mm */,
- 352742831D4C244700A1ECE6 /* MGLRasterSource.h */,
- DA7DC9821DED647F0027472F /* MGLRasterSource_Private.h */,
- 352742841D4C244700A1ECE6 /* MGLRasterSource.mm */,
+ 352742831D4C244700A1ECE6 /* MGLRasterTileSource.h */,
+ DA7DC9821DED647F0027472F /* MGLRasterTileSource_Private.h */,
+ 352742841D4C244700A1ECE6 /* MGLRasterTileSource.mm */,
DACA8620201920BE00E9693A /* MGLRasterDEMSource.h */,
DACA8621201920BE00E9693A /* MGLRasterDEMSource.mm */,
352742871D4C245800A1ECE6 /* MGLShapeSource.h */,
@@ -734,9 +736,9 @@
DA551B7F1DB496AC0009AFAF /* MGLTileSource.h */,
DA551B801DB496AC0009AFAF /* MGLTileSource_Private.h */,
DA551B811DB496AC0009AFAF /* MGLTileSource.mm */,
- DA8F25951D51CAC70010E6B5 /* MGLVectorSource.h */,
- DA7DC9801DED5F5C0027472F /* MGLVectorSource_Private.h */,
- DA8F25961D51CAC70010E6B5 /* MGLVectorSource.mm */,
+ DA8F25951D51CAC70010E6B5 /* MGLVectorTileSource.h */,
+ DA7DC9801DED5F5C0027472F /* MGLVectorTileSource_Private.h */,
+ DA8F25961D51CAC70010E6B5 /* MGLVectorTileSource.mm */,
07A019EB1ED662D800ACD43E /* MGLImageSource.h */,
07A019EC1ED662D800ACD43E /* MGLImageSource.mm */,
);
@@ -1183,7 +1185,7 @@
DA8F258F1D51CA600010E6B5 /* MGLRasterStyleLayer.h in Headers */,
3508EC641D749D39009B0EE4 /* NSExpression+MGLAdditions.h in Headers */,
DAE6C38D1CC31E2A00DB3429 /* MGLOfflineRegion_Private.h in Headers */,
- DA7DC9831DED647F0027472F /* MGLRasterSource_Private.h in Headers */,
+ DA7DC9831DED647F0027472F /* MGLRasterTileSource_Private.h in Headers */,
1753ED401E53CE6100A9FD90 /* MGLConversion.h in Headers */,
DA8F259C1D51CB000010E6B5 /* MGLStyleValue_Private.h in Headers */,
DAE6C35B1CC31E0400DB3429 /* MGLAnnotation.h in Headers */,
@@ -1212,13 +1214,13 @@
DAE6C35F1CC31E0400DB3429 /* MGLOfflinePack.h in Headers */,
DAE6C39C1CC31E2A00DB3429 /* NSString+MGLAdditions.h in Headers */,
3529039B1D6C63B80002C7DF /* NSPredicate+MGLAdditions.h in Headers */,
- DA8F25971D51CAC70010E6B5 /* MGLVectorSource.h in Headers */,
- DA7DC9811DED5F5C0027472F /* MGLVectorSource_Private.h in Headers */,
+ DA8F25971D51CAC70010E6B5 /* MGLVectorTileSource.h in Headers */,
+ DA7DC9811DED5F5C0027472F /* MGLVectorTileSource_Private.h in Headers */,
DAE6C3861CC31E2A00DB3429 /* MGLGeometry_Private.h in Headers */,
DAE6C3841CC31E2A00DB3429 /* MGLAccountManager_Private.h in Headers */,
DACA8622201920BE00E9693A /* MGLRasterDEMSource.h in Headers */,
DAE6C3691CC31E0400DB3429 /* MGLTypes.h in Headers */,
- 07D9474D1F67441B00E37934 /* MGLAbstractShapeSource_Private.h in Headers */,
+ 07D9474D1F67441B00E37934 /* MGLComputedShapeSource_Private.h in Headers */,
DAE6C3991CC31E2A00DB3429 /* NSException+MGLAdditions.h in Headers */,
DA8F25871D51C9E10010E6B5 /* MGLBackgroundStyleLayer.h in Headers */,
4049C2A51DB6CE7F00B3F799 /* MGLPointCollection.h in Headers */,
@@ -1234,7 +1236,6 @@
35602BFA1D3EA99F0050646F /* MGLFillStyleLayer.h in Headers */,
DA35A2A41CC9EB1A00E826B2 /* MGLCoordinateFormatter.h in Headers */,
35C5D8491D6DD66D00E95907 /* NSCompoundPredicate+MGLAdditions.h in Headers */,
- 07D9474C1F67441500E37934 /* MGLAbstractShapeSource.h in Headers */,
DD0902B31DB1AC6400C5BDCE /* MGLNetworkConfiguration.h in Headers */,
DAE6C3621CC31E0400DB3429 /* MGLOverlay.h in Headers */,
DAE6C3651CC31E0400DB3429 /* MGLPolyline.h in Headers */,
@@ -1273,7 +1274,7 @@
DAE6C3891CC31E2A00DB3429 /* MGLMultiPoint_Private.h in Headers */,
DAE6C3A51CC31E9400DB3429 /* MGLMapView+IBAdditions.h in Headers */,
DA35A2AD1CCA091800E826B2 /* MGLCompassDirectionFormatter.h in Headers */,
- 352742851D4C244700A1ECE6 /* MGLRasterSource.h in Headers */,
+ 352742851D4C244700A1ECE6 /* MGLRasterTileSource.h in Headers */,
9654C12D1FFC394700DB6A19 /* MGLPolygon_Private.h in Headers */,
408AA85B1DAEECFE00022900 /* MGLShape_Private.h in Headers */,
DACC22181CF3D4F700D220D9 /* MGLFeature_Private.h in Headers */,
@@ -1374,7 +1375,7 @@
TargetAttributes = {
DA839E911CC2E3400062CAFB = {
CreatedOnToolsVersion = 7.3;
- LastSwiftMigration = 0830;
+ LastSwiftMigration = 0920;
};
DAAA17961CE13BAE00731EFE = {
CreatedOnToolsVersion = 7.3.1;
@@ -1384,7 +1385,7 @@
};
DAE6C3301CC30DB200DB3429 = {
CreatedOnToolsVersion = 7.3;
- LastSwiftMigration = 0800;
+ LastSwiftMigration = 0920;
};
};
};
@@ -1415,6 +1416,8 @@
bg,
ar,
he,
+ da,
+ "pt-PT",
);
mainGroup = DA839E891CC2E3400062CAFB;
productRefGroup = DA839E931CC2E3400062CAFB /* Products */;
@@ -1513,11 +1516,10 @@
DAE6C3B31CC31EF300DB3429 /* MGLAttributionButton.mm in Sources */,
35602BFB1D3EA99F0050646F /* MGLFillStyleLayer.mm in Sources */,
DAE6C3931CC31E2A00DB3429 /* MGLShape.mm in Sources */,
- 352742861D4C244700A1ECE6 /* MGLRasterSource.mm in Sources */,
+ 352742861D4C244700A1ECE6 /* MGLRasterTileSource.mm in Sources */,
558DE7A71E56161C00C7916D /* MGLFoundation.mm in Sources */,
DAE6C39D1CC31E2A00DB3429 /* NSString+MGLAdditions.m in Sources */,
3598195A1E02F611008FC139 /* NSCoder+MGLAdditions.mm in Sources */,
- 07D9474B1F6743F000E37934 /* MGLAbstractShapeSource.mm in Sources */,
DAE6C3941CC31E2A00DB3429 /* MGLStyle.mm in Sources */,
DAE6C3871CC31E2A00DB3429 /* MGLGeometry.mm in Sources */,
894623A0200E748000DA8EF2 /* MGLHeatmapStyleLayer.mm in Sources */,
@@ -1561,7 +1563,7 @@
DA8F258C1D51CA540010E6B5 /* MGLLineStyleLayer.mm in Sources */,
DA8F25941D51CA750010E6B5 /* MGLSymbolStyleLayer.mm in Sources */,
3529039C1D6C63B80002C7DF /* NSPredicate+MGLAdditions.mm in Sources */,
- DA8F25981D51CAC70010E6B5 /* MGLVectorSource.mm in Sources */,
+ DA8F25981D51CAC70010E6B5 /* MGLVectorTileSource.mm in Sources */,
352742A11D4C25BD00A1ECE6 /* MGLStyleValue.mm in Sources */,
3EA93BA38DBB4B814B6C1FCC /* MGLRendererConfiguration.mm in Sources */,
);
@@ -1653,6 +1655,8 @@
DA3389611FA3EDCE001EA329 /* bg */,
DA80E95D1FE84A300065FC9B /* ar */,
DACBC6082011885800C4D7E2 /* he */,
+ DAD88E03202ACF5900AAA536 /* da */,
+ DA934097208562590059919A /* pt-PT */,
);
name = Localizable.strings;
sourceTree = "<group>";
@@ -1704,6 +1708,9 @@
DA704CBF1F637548004B3F28 /* hu */,
DA3389641FA3EE00001EA329 /* bg */,
DACBC60A2011889E00C4D7E2 /* he */,
+ DAD88E06202ACF9200AAA536 /* da */,
+ DA9340992085629E0059919A /* pt-PT */,
+ DA9340A0208565870059919A /* ar */,
);
name = Localizable.strings;
sourceTree = "<group>";
@@ -1727,6 +1734,7 @@
DA3389601FA3EAC4001EA329 /* pt-BR */,
DA3389621FA3EDEF001EA329 /* bg */,
DACBC6092011888C00C4D7E2 /* he */,
+ DAD88E04202ACF7C00AAA536 /* da */,
);
name = Foundation.strings;
sourceTree = "<group>";
@@ -1749,6 +1757,8 @@
DA3389631FA3EDF5001EA329 /* bg */,
DA33896C1FA3EF51001EA329 /* hu */,
DA80E95F1FE84A540065FC9B /* ar */,
+ DAD88E05202ACF8200AAA536 /* da */,
+ DA934098208562870059919A /* pt-PT */,
);
name = Foundation.stringsdict;
sourceTree = "<group>";
@@ -1876,7 +1886,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.MapboxGL;
PRODUCT_NAME = "Mapbox GL";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -1891,7 +1901,7 @@
OTHER_CFLAGS = "-fvisibility=hidden";
PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.MapboxGL;
PRODUCT_NAME = "Mapbox GL";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Release;
};
@@ -2017,7 +2027,7 @@
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "../darwin/test/test-Bridging-Header.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Debug;
};
@@ -2044,7 +2054,7 @@
PRODUCT_BUNDLE_IDENTIFIER = com.mapbox.test;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_OBJC_BRIDGING_HEADER = "../darwin/test/test-Bridging-Header.h";
- SWIFT_VERSION = 3.0;
+ SWIFT_VERSION = 4.0;
};
name = Release;
};
diff --git a/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme b/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme
index b0ce01fbf0..aab7486fbe 100644
--- a/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme
+++ b/platform/macos/macos.xcodeproj/xcshareddata/xcschemes/macosapp.xcscheme
@@ -26,7 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- language = ""
+ language = "en"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
@@ -56,7 +56,6 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
- language = ""
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
diff --git a/platform/macos/sdk/ar.lproj/Localizable.strings b/platform/macos/sdk/ar.lproj/Localizable.strings
new file mode 100644
index 0000000000..fb0b0a2a46
--- /dev/null
+++ b/platform/macos/sdk/ar.lproj/Localizable.strings
@@ -0,0 +1,27 @@
+/* User-friendly error description */
+"LOAD_MAP_FAILED_DESC" = "فشل تحميل الخريطة بسبب حدوث خطأ مجهول.";
+
+/* User-friendly error description */
+"LOAD_STYLE_FAILED_DESC" = "فشل تحميل الخريطة بسبب تعذر تحميل النمط.";
+
+/* Accessibility title */
+"MAP_A11Y_TITLE" = "Mapbox";
+
+/* User-friendly error description */
+"PARSE_STYLE_FAILED_DESC" = "فشل تحميل الخريطة لأن النمط تالف.";
+
+/* User-friendly error description */
+"STYLE_NOT_FOUND_DESC" = "فشل تحميل الخريطة بسبب تعذر العثور على النمط أو أنه غير متوافق";
+
+/* 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/sdk/da.lproj/Localizable.strings b/platform/macos/sdk/da.lproj/Localizable.strings
new file mode 100644
index 0000000000..1c9dcaa68d
--- /dev/null
+++ b/platform/macos/sdk/da.lproj/Localizable.strings
@@ -0,0 +1,27 @@
+/* User-friendly error description */
+"LOAD_MAP_FAILED_DESC" = "Kortet kunne ikke indlæses, fordi der opstod en ukendt fejl.";
+
+/* User-friendly error description */
+"LOAD_STYLE_FAILED_DESC" = "Kortet kunne ikke indlæses, fordi benævnelsen ikke kan indlæses.";
+
+/* Accessibility title */
+"MAP_A11Y_TITLE" = "Mapbox";
+
+/* User-friendly error description */
+"PARSE_STYLE_FAILED_DESC" = "Kortet kunne ikke indlæses, fordi benævnelsen er beskadiget.";
+
+/* User-friendly error description */
+"STYLE_NOT_FOUND_DESC" = "Kortet kunne ikke indlæses, fordi benævnelsen ikke kan findes eller er uforenelig.";
+
+/* Label of Zoom In button */
+"ZOOM_IN_LABEL" = "+";
+
+/* Tooltip of Zoom In button */
+"ZOOM_IN_TOOLTIP" = "Zoom Ind";
+
+/* Label of Zoom Out button; U+2212 MINUS SIGN */
+"ZOOM_OUT_LABEL" = "−";
+
+/* Tooltip of Zoom Out button */
+"ZOOM_OUT_TOOLTIP" = "Zoom Ud";
+
diff --git a/platform/macos/sdk/hu.lproj/Localizable.strings b/platform/macos/sdk/hu.lproj/Localizable.strings
index b3724190cb..062b1f5cea 100644
--- a/platform/macos/sdk/hu.lproj/Localizable.strings
+++ b/platform/macos/sdk/hu.lproj/Localizable.strings
@@ -1,8 +1,8 @@
-/* User-friendly error description */
+/* User-friendly error description */
"LOAD_MAP_FAILED_DESC" = "Egy ismeretlen hiba miatt nem sikerült betölteni a térképet.";
/* User-friendly error description */
-"LOAD_STYLE_FAILED_DESC" = "Nem sikerült betölteni a térképet, mert a stílus nem tölthető be.";
+"LOAD_STYLE_FAILED_DESC" = "Nem sikerült betölteni a térképet, mert a stílust nem lehetett betölteni.";
/* Accessibility title */
"MAP_A11Y_TITLE" = "Mapbox";
diff --git a/platform/macos/sdk/pt-PT.lproj/Localizable.strings b/platform/macos/sdk/pt-PT.lproj/Localizable.strings
new file mode 100644
index 0000000000..1385193989
--- /dev/null
+++ b/platform/macos/sdk/pt-PT.lproj/Localizable.strings
@@ -0,0 +1,27 @@
+/* User-friendly error description */
+"LOAD_MAP_FAILED_DESC" = "Não foi possível carregar o mapa porque ocorreu um erro.";
+
+/* User-friendly error description */
+"LOAD_STYLE_FAILED_DESC" = "Não foi possível carregar o mapa porque o estilo não foi carregado.";
+
+/* Accessibility title */
+"MAP_A11Y_TITLE" = "Mapbox";
+
+/* User-friendly error description */
+"PARSE_STYLE_FAILED_DESC" = "Não foi possível carregar o mapa porque o estilo está corrompido.";
+
+/* User-friendly error description */
+"STYLE_NOT_FOUND_DESC" = "Não foi possível carregar o mapa porque o estilo não foi encontrado ou não é compatível.";
+
+/* Label of Zoom In button */
+"ZOOM_IN_LABEL" = "+";
+
+/* Tooltip of Zoom In button */
+"ZOOM_IN_TOOLTIP" = "Apromixar";
+
+/* Label of Zoom Out button; U+2212 MINUS SIGN */
+"ZOOM_OUT_LABEL" = "−";
+
+/* Tooltip of Zoom Out button */
+"ZOOM_OUT_TOOLTIP" = "Afastar";
+
diff --git a/platform/macos/sdk/ru.lproj/Localizable.strings b/platform/macos/sdk/ru.lproj/Localizable.strings
index 067e05b14e..8554c9ebd1 100644
--- a/platform/macos/sdk/ru.lproj/Localizable.strings
+++ b/platform/macos/sdk/ru.lproj/Localizable.strings
@@ -1,8 +1,8 @@
-/* User-friendly error description */
-"LOAD_MAP_FAILED_DESC" = "Не удалось загрузит карту из-за неизвестной ошибки.";
+/* User-friendly error description */
+"LOAD_MAP_FAILED_DESC" = "Не удалось загрузить карту из-за неизвестной ошибки.";
/* User-friendly error description */
-"LOAD_STYLE_FAILED_DESC" = "Не удалось загрузить карту так как невозможно загрузить стиль.";
+"LOAD_STYLE_FAILED_DESC" = "Не удалось загрузить карту из-за ошибки загрузки стиля.";
/* Accessibility title */
"MAP_A11Y_TITLE" = "Mapbox";
diff --git a/platform/macos/src/MGLMapView.h b/platform/macos/src/MGLMapView.h
index 96b0932c14..e3de1069a9 100644
--- a/platform/macos/src/MGLMapView.h
+++ b/platform/macos/src/MGLMapView.h
@@ -397,11 +397,10 @@ MGL_EXPORT IB_DESIGNABLE
want to animate the change, use the `-setVisibleCoordinateBounds:animated:`
method instead.
- If a longitude is less than −180 degrees or greater than 180 degrees, the visible
- bounds straddles the antimeridian or international date line.
-
- For example, a visible bounds that stretches from Tokyo to San Francisco would have
- coordinates of (35.68476, -220.24257) and (37.78428, -122.41310).
+ If a longitude is less than −180 degrees or greater than 180 degrees, the
+ visible bounds straddles the antimeridian or international date line. For
+ example, if both Tokyo and San Francisco are visible, the visible bounds might
+ extend from (35.68476, −220.24257) to (37.78428, −122.41310).
*/
@property (nonatomic) MGLCoordinateBounds visibleCoordinateBounds;
@@ -409,11 +408,10 @@ MGL_EXPORT IB_DESIGNABLE
Changes the receiver’s viewport to fit the given coordinate bounds, optionally
animating the change.
- To make the visible bounds go across the antimeridian or international date line,
- specify some longitudes less than −180 degrees or greater than 180 degrees.
-
- For example, a visible bounds that stretches from Tokyo to San Francisco would have
- coordinates of (35.68476, -220.24257) and (37.78428, -122.41310).
+ To bring both sides of the antimeridian or international date line into view,
+ specify some longitudes less than −180 degrees or greater than 180 degrees. For
+ example, to show both Tokyo and San Francisco simultaneously, you could set the
+ visible bounds to extend from (35.68476, −220.24257) to (37.78428, −122.41310).
@param bounds The bounds that the viewport will show in its entirety.
@param animated Specify `YES` to animate the change by smoothly scrolling and
@@ -723,16 +721,27 @@ MGL_EXPORT IB_DESIGNABLE
Assigning a new array to this property selects only the first annotation in the
array.
+
+ If the annotation is of type `MGLPointAnnotation` and is offscreen, the map is
+ panned so that the annotation and its callout are brought just onscreen. The
+ annotation is *not* centered within the viewport.
+
+ @note In versions prior to `4.0.0` if the annotation was offscreen it was not
+ selected.
*/
@property (nonatomic, copy) NS_ARRAY_OF(id <MGLAnnotation>) *selectedAnnotations;
/**
Selects an annotation and displays a callout popover for it.
- If the given annotation is not visible within the current viewport, this method
- has no effect.
+ If the annotation is of type `MGLPointAnnotation` and is offscreen, the map is
+ panned so that the annotation and its callout are brought just onscreen. The
+ annotation is *not* centered within the viewport.
@param annotation The annotation object to select.
+
+ @note In versions prior to `4.0.0` selecting an offscreen annotation did not
+ change the camera.
*/
- (void)selectAnnotation:(id <MGLAnnotation>)annotation;
@@ -866,9 +875,9 @@ MGL_EXPORT IB_DESIGNABLE
Each object in the returned array represents a feature rendered by the
current style and provides access to attributes specified by the relevant map
content sources. The returned array includes features loaded by
- `MGLShapeSource` and `MGLVectorSource` objects but does not include anything
- from `MGLRasterSource` objects, or from image, video, or canvas sources, which
- are unsupported by this SDK.
+ `MGLShapeSource` and `MGLVectorTileSource` objects but does not include
+ anything from `MGLRasterTileSource` objects, or from video or canvas sources,
+ which are unsupported by this SDK.
The returned features are drawn by a style layer in the current style. For
example, suppose the current style uses the
@@ -900,7 +909,7 @@ MGL_EXPORT IB_DESIGNABLE
Only visible features are returned. To obtain features regardless of
visibility, use the
- `-[MGLVectorSource featuresInSourceLayersWithIdentifiers:predicate:]` and
+ `-[MGLVectorTileSource featuresInSourceLayersWithIdentifiers:predicate:]` and
`-[MGLShapeSource featuresMatchingPredicate:]` methods on the relevant sources.
@note Layer identifiers are not guaranteed to exist across styles or different
@@ -963,9 +972,9 @@ MGL_EXPORT IB_DESIGNABLE
Each object in the returned array represents a feature rendered by the
current style and provides access to attributes specified by the relevant map
content sources. The returned array includes features loaded by
- `MGLShapeSource` and `MGLVectorSource` objects but does not include anything
- from `MGLRasterSource` objects, or from image, video, or canvas sources, which
- are unsupported by this SDK.
+ `MGLShapeSource` and `MGLVectorTileSource` objects but does not include
+ anything from `MGLRasterTileSource` objects, or from video or canvas sources,
+ which are unsupported by this SDK.
The returned features are drawn by a style layer in the current style. For
example, suppose the current style uses the
@@ -998,7 +1007,7 @@ MGL_EXPORT IB_DESIGNABLE
Only visible features are returned. To obtain features regardless of
visibility, use the
- `-[MGLVectorSource featuresInSourceLayersWithIdentifiers:predicate:]` and
+ `-[MGLVectorTileSource featuresInSourceLayersWithIdentifiers:predicate:]` and
`-[MGLShapeSource featuresMatchingPredicate:]` methods on the relevant sources.
@note Layer identifiers are not guaranteed to exist across styles or different
@@ -1060,6 +1069,9 @@ MGL_EXPORT IB_DESIGNABLE
/**
Converts a rectangle in the given view’s coordinate system to a geographic
bounding box.
+
+ If a longitude is less than −180 degrees or greater than 180 degrees, the
+ bounding box straddles the antimeridian or international date line.
@param rect The rectangle to convert.
@param view The view in whose coordinate system the rectangle is expressed.
diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm
index 9ec9012198..9cab9a76da 100644
--- a/platform/macos/src/MGLMapView.mm
+++ b/platform/macos/src/MGLMapView.mm
@@ -97,6 +97,9 @@ const CGFloat MGLAnnotationImagePaddingForHitTest = 4;
/// Distance from the callout’s anchor point to the annotation it points to.
const CGFloat MGLAnnotationImagePaddingForCallout = 4;
+/// Padding to edge of view that an offscreen annotation must have when being brought onscreen (by being selected)
+const NSEdgeInsets MGLMapViewOffscreenAnnotationPadding = NSEdgeInsetsMake(-30.0f, -30.0f, -30.0f, -30.0f);
+
/// Unique identifier representing a single annotation in mbgl.
typedef uint32_t MGLAnnotationTag;
@@ -2099,44 +2102,41 @@ public:
MGLAnnotationTag hitAnnotationTag = MGLAnnotationTagNotFound;
if (nearbyAnnotations.size()) {
- // The annotation tags need to be stable in order to compare them with
- // the remembered tags.
- std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end());
-
+ // The first selection in the cycle should be the one nearest to the
+ // tap. Also the annotation tags need to be stable in order to compare them with
+ // the remembered tags _annotationsNearbyLastClick.
+ CLLocationCoordinate2D currentCoordinate = [self convertPoint:point toCoordinateFromView:self];
+ std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag tagA, const MGLAnnotationTag tagB) {
+ CLLocationCoordinate2D coordinateA = [[self annotationWithTag:tagA] coordinate];
+ CLLocationCoordinate2D coordinateB = [[self annotationWithTag:tagB] coordinate];
+ CLLocationDegrees deltaA = hypot(coordinateA.latitude - currentCoordinate.latitude,
+ coordinateA.longitude - currentCoordinate.longitude);
+ CLLocationDegrees deltaB = hypot(coordinateB.latitude - currentCoordinate.latitude,
+ coordinateB.longitude - currentCoordinate.longitude);
+ return deltaA < deltaB;
+ });
+
if (nearbyAnnotations == _annotationsNearbyLastClick) {
- // The first selection in the cycle should be the one nearest to the
- // click.
- CLLocationCoordinate2D currentCoordinate = [self convertPoint:point toCoordinateFromView:self];
- std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end(), [&](const MGLAnnotationTag tagA, const MGLAnnotationTag tagB) {
- CLLocationCoordinate2D coordinateA = [[self annotationWithTag:tagA] coordinate];
- CLLocationCoordinate2D coordinateB = [[self annotationWithTag:tagB] coordinate];
- CLLocationDegrees distanceA = hypot(coordinateA.latitude - currentCoordinate.latitude,
- coordinateA.longitude - currentCoordinate.longitude);
- CLLocationDegrees distanceB = hypot(coordinateB.latitude - currentCoordinate.latitude,
- coordinateB.longitude - currentCoordinate.longitude);
- return distanceA < distanceB;
- });
-
// The last time we persisted a set of annotations, we had the same
// set of annotations as we do now. Cycle through them.
if (_lastSelectedAnnotationTag == MGLAnnotationTagNotFound
- || _lastSelectedAnnotationTag == _annotationsNearbyLastClick.back()) {
+ || _lastSelectedAnnotationTag == nearbyAnnotations.back()) {
// Either no annotation is selected or the last annotation in
// the set was selected. Wrap around to the first annotation in
// the set.
- hitAnnotationTag = _annotationsNearbyLastClick.front();
+ hitAnnotationTag = nearbyAnnotations.front();
} else {
- auto result = std::find(_annotationsNearbyLastClick.begin(),
- _annotationsNearbyLastClick.end(),
+ auto result = std::find(nearbyAnnotations.begin(),
+ nearbyAnnotations.end(),
_lastSelectedAnnotationTag);
- if (result == _annotationsNearbyLastClick.end()) {
+ if (result == nearbyAnnotations.end()) {
// An annotation from this set hasn’t been selected before.
// Select the first (nearest) one.
- hitAnnotationTag = _annotationsNearbyLastClick.front();
+ hitAnnotationTag = nearbyAnnotations.front();
} else {
// Step to the next annotation in the set.
- auto distance = std::distance(_annotationsNearbyLastClick.begin(), result);
- hitAnnotationTag = _annotationsNearbyLastClick[distance + 1];
+ auto distance = std::distance(nearbyAnnotations.begin(), result);
+ hitAnnotationTag = nearbyAnnotations[distance + 1];
}
}
} else {
@@ -2208,10 +2208,12 @@ public:
return;
}
- // Select the annotation if it’s visible.
- if (MGLCoordinateInCoordinateBounds(firstAnnotation.coordinate, self.visibleCoordinateBounds)) {
- [self selectAnnotation:firstAnnotation];
- }
+ [self selectAnnotation:firstAnnotation];
+}
+
+- (BOOL)isBringingAnnotationOnscreenSupportedForAnnotation:(id<MGLAnnotation>)annotation animated:(BOOL)animated {
+ // Consider delegating
+ return animated && [annotation isKindOfClass:[MGLPointAnnotation class]];
}
- (void)selectAnnotation:(id <MGLAnnotation>)annotation
@@ -2221,6 +2223,11 @@ public:
- (void)selectAnnotation:(id <MGLAnnotation>)annotation atPoint:(NSPoint)gesturePoint
{
+ [self selectAnnotation:annotation atPoint:gesturePoint moveOnscreen:YES animateSelection:YES];
+}
+
+- (void)selectAnnotation:(id <MGLAnnotation>)annotation atPoint:(NSPoint)gesturePoint moveOnscreen:(BOOL)moveOnscreen animateSelection:(BOOL)animateSelection
+{
id <MGLAnnotation> selectedAnnotation = self.selectedAnnotation;
if (annotation == selectedAnnotation) {
return;
@@ -2235,9 +2242,14 @@ public:
[self addAnnotation:annotation];
}
+ if (moveOnscreen) {
+ moveOnscreen = [self isBringingAnnotationOnscreenSupportedForAnnotation:annotation animated:animateSelection];
+ }
+
// The annotation's anchor will bounce to the current click.
NSRect positioningRect = [self positioningRectForCalloutForAnnotationWithTag:annotationTag];
- if (NSIsEmptyRect(NSIntersectionRect(positioningRect, self.bounds))) {
+
+ if (!moveOnscreen && NSIsEmptyRect(NSIntersectionRect(positioningRect, self.bounds))) {
positioningRect = CGRectMake(gesturePoint.x, gesturePoint.y, positioningRect.size.width, positioningRect.size.height);
}
@@ -2257,11 +2269,65 @@ public:
// alignment rect, or off the left edge in a right-to-left UI.
callout.delegate = self;
self.calloutForSelectedAnnotation = callout;
+
NSRectEdge edge = (self.userInterfaceLayoutDirection == NSUserInterfaceLayoutDirectionRightToLeft
? NSMinXEdge
: NSMaxXEdge);
+
+ // The following will do nothing if the positioning rect is not on-screen. See
+ // `-[MGLMapView updateAnnotationCallouts]` for presenting the callout when the selected
+ // annotation comes back on-screen.
[callout showRelativeToRect:positioningRect ofView:self preferredEdge:edge];
}
+
+ if (moveOnscreen)
+ {
+ moveOnscreen = NO;
+
+ NSRect (^edgeInsetsInsetRect)(NSRect, NSEdgeInsets) = ^(NSRect rect, NSEdgeInsets insets) {
+ return NSMakeRect(rect.origin.x + insets.left,
+ rect.origin.y + insets.top,
+ rect.size.width - insets.left - insets.right,
+ rect.size.height - insets.top - insets.bottom);
+ };
+
+ // Add padding around the positioning rect (in essence an inset from the edge of the viewport
+ NSRect expandedPositioningRect = edgeInsetsInsetRect(positioningRect, MGLMapViewOffscreenAnnotationPadding);
+
+ // Used for callout positioning, and moving offscreen annotations onscreen.
+ CGRect constrainedRect = edgeInsetsInsetRect(self.bounds, self.contentInsets);
+ CGRect bounds = constrainedRect;
+
+ // Any one of these cases should trigger a move onscreen
+ if (CGRectGetMinX(positioningRect) < CGRectGetMinX(bounds))
+ {
+ constrainedRect.origin.x = expandedPositioningRect.origin.x;
+ moveOnscreen = YES;
+ }
+ else if (CGRectGetMaxX(positioningRect) > CGRectGetMaxX(bounds))
+ {
+ constrainedRect.origin.x = CGRectGetMaxX(expandedPositioningRect) - constrainedRect.size.width;
+ moveOnscreen = YES;
+ }
+
+ if (CGRectGetMinY(positioningRect) < CGRectGetMinY(bounds))
+ {
+ constrainedRect.origin.y = expandedPositioningRect.origin.y;
+ moveOnscreen = YES;
+ }
+ else if (CGRectGetMaxY(positioningRect) > CGRectGetMaxY(bounds))
+ {
+ constrainedRect.origin.y = CGRectGetMaxY(expandedPositioningRect) - constrainedRect.size.height;
+ moveOnscreen = YES;
+ }
+
+ if (moveOnscreen)
+ {
+ CGPoint center = CGPointMake(CGRectGetMidX(constrainedRect), CGRectGetMidY(constrainedRect));
+ CLLocationCoordinate2D centerCoord = [self convertPoint:center toCoordinateFromView:self];
+ [self setCenterCoordinate:centerCoord animated:animateSelection];
+ }
+ }
}
- (void)showAnnotations:(NS_ARRAY_OF(id <MGLAnnotation>) *)annotations animated:(BOOL)animated {
@@ -2396,7 +2462,25 @@ public:
- (void)updateAnnotationCallouts {
NSPopover *callout = self.calloutForSelectedAnnotation;
if (callout) {
- callout.positioningRect = [self positioningRectForCalloutForAnnotationWithTag:_selectedAnnotationTag];
+ NSRect rect = [self positioningRectForCalloutForAnnotationWithTag:_selectedAnnotationTag];
+
+ if (!NSIsEmptyRect(NSIntersectionRect(rect, self.bounds))) {
+
+ // It's possible that the current callout hasn't been presented (since the original
+ // positioningRect was offscreen). We can check that the callout has a valid window
+ // This results in the callout being presented just as the annotation comes on screen
+ // which matches MapKit, but (currently) not iOS.
+ if (!callout.contentViewController.view.window) {
+ NSRectEdge edge = (self.userInterfaceLayoutDirection == NSUserInterfaceLayoutDirectionRightToLeft
+ ? NSMinXEdge
+ : NSMaxXEdge);
+ // Re-present the callout
+ [callout showRelativeToRect:rect ofView:self preferredEdge:edge];
+ }
+ else {
+ callout.positioningRect = rect;
+ }
+ }
}
}
@@ -2717,32 +2801,24 @@ public:
/// Converts a rectangle in the given view’s coordinate system to a geographic
/// bounding box.
- (mbgl::LatLngBounds)convertRect:(NSRect)rect toLatLngBoundsFromView:(nullable NSView *)view {
- mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty();
- bounds.extend([self convertPoint:rect.origin toLatLngFromView:view]);
- bounds.extend([self convertPoint:{ NSMaxX(rect), NSMinY(rect) } toLatLngFromView:view]);
- bounds.extend([self convertPoint:{ NSMaxX(rect), NSMaxY(rect) } toLatLngFromView:view]);
- bounds.extend([self convertPoint:{ NSMinX(rect), NSMaxY(rect) } toLatLngFromView:view]);
-
- // The world is wrapping if a point just outside the bounds is also within
- // the rect.
- mbgl::LatLng outsideLatLng;
- if (bounds.west() > -180) {
- outsideLatLng = {
- (bounds.south() + bounds.north()) / 2,
- bounds.west() - 1,
- };
- } else if (bounds.northeast().longitude() < 180) {
- outsideLatLng = {
- (bounds.south() + bounds.north()) / 2,
- bounds.east() + 1,
- };
- }
-
- // If the world is wrapping, extend the bounds to cover all longitudes.
- if (NSPointInRect([self convertLatLng:outsideLatLng toPointToView:view], rect)) {
- bounds.extend(mbgl::LatLng(bounds.south(), -180));
- bounds.extend(mbgl::LatLng(bounds.south(), 180));
- }
+ auto bounds = mbgl::LatLngBounds::empty();
+ auto bottomLeft = [self convertPoint:{ NSMinX(rect), NSMinY(rect) } toLatLngFromView:view];
+ auto bottomRight = [self convertPoint:{ NSMaxX(rect), NSMinY(rect) } toLatLngFromView:view];
+ auto topRight = [self convertPoint:{ NSMaxX(rect), NSMaxY(rect) } toLatLngFromView:view];
+ auto topLeft = [self convertPoint:{ NSMinX(rect), NSMaxY(rect) } toLatLngFromView:view];
+
+ // If the bounds straddles the antimeridian, unwrap it so that one side
+ // extends beyond ±180° longitude.
+ auto center = [self convertPoint:{ NSMidX(rect), NSMidY(rect) } toLatLngFromView:view];
+ bottomLeft.unwrapForShortestPath(center);
+ bottomRight.unwrapForShortestPath(center);
+ topRight.unwrapForShortestPath(center);
+ topLeft.unwrapForShortestPath(center);
+
+ bounds.extend(bottomLeft);
+ bounds.extend(bottomRight);
+ bounds.extend(topRight);
+ bounds.extend(topLeft);
return bounds;
}
diff --git a/platform/macos/src/Mapbox.h b/platform/macos/src/Mapbox.h
index 0e4b546cf7..fcf41203cf 100644
--- a/platform/macos/src/Mapbox.h
+++ b/platform/macos/src/Mapbox.h
@@ -49,11 +49,10 @@ FOUNDATION_EXPORT MGL_EXPORT const unsigned char MapboxVersionString[];
#import "MGLOpenGLStyleLayer.h"
#import "MGLSource.h"
#import "MGLTileSource.h"
-#import "MGLVectorSource.h"
+#import "MGLVectorTileSource.h"
#import "MGLShapeSource.h"
-#import "MGLAbstractShapeSource.h"
#import "MGLComputedShapeSource.h"
-#import "MGLRasterSource.h"
+#import "MGLRasterTileSource.h"
#import "MGLRasterDEMSource.h"
#import "MGLImageSource.h"
#import "MGLTilePyramidOfflineRegion.h"
diff --git a/platform/macos/src/NSColor+MGLAdditions.h b/platform/macos/src/NSColor+MGLAdditions.h
index 8dd8c1c17c..21c939fec6 100644
--- a/platform/macos/src/NSColor+MGLAdditions.h
+++ b/platform/macos/src/NSColor+MGLAdditions.h
@@ -6,7 +6,7 @@
@interface NSColor (MGLAdditions)
/**
- Converts the color into an mbgl::Color in calibrated RGB space.
+ Converts the color into an mbgl::Color in sRGB space.
*/
- (mbgl::Color)mgl_color;
@@ -18,3 +18,10 @@
- (mbgl::style::PropertyValue<mbgl::Color>)mgl_colorPropertyValue;
@end
+
+@interface NSExpression (MGLColorAdditions)
+
++ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components;
++ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components;
+
+@end
diff --git a/platform/macos/src/NSColor+MGLAdditions.mm b/platform/macos/src/NSColor+MGLAdditions.mm
index 5288f2bc61..8c9086ccf7 100644
--- a/platform/macos/src/NSColor+MGLAdditions.mm
+++ b/platform/macos/src/NSColor+MGLAdditions.mm
@@ -2,24 +2,98 @@
@implementation NSColor (MGLAdditions)
-- (mbgl::Color)mgl_color
-{
+- (mbgl::Color)mgl_color {
CGFloat r, g, b, a;
- [[self colorUsingColorSpaceName:NSCalibratedRGBColorSpace] getRed:&r green:&g blue:&b alpha:&a];
+ // The Mapbox Style Specification does not specify a color space, but it is
+ // assumed to be sRGB for consistency with CSS.
+ NSColor *srgbColor = self;
+ if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) {
+ srgbColor = [srgbColor colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+ } else {
+ srgbColor = [srgbColor colorUsingColorSpace:[NSColorSpace sRGBColorSpace]];
+ }
+ [srgbColor getRed:&r green:&g blue:&b alpha:&a];
return { (float)r, (float)g, (float)b, (float)a };
}
-+ (NSColor *)mgl_colorWithColor:(mbgl::Color)color
-{
- return [NSColor colorWithCalibratedRed:color.r green:color.g blue:color.b alpha:color.a];
++ (NSColor *)mgl_colorWithColor:(mbgl::Color)color {
+ // macOS 10.12 Sierra and below uses calibrated RGB by default.
+ if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) {
+ return [NSColor colorWithCalibratedRed:color.r green:color.g blue:color.b alpha:color.a];
+ } else {
+ return [NSColor colorWithRed:color.r green:color.g blue:color.b alpha:color.a];
+ }
}
-- (mbgl::style::PropertyValue<mbgl::Color>)mgl_colorPropertyValue
-{
+- (mbgl::style::PropertyValue<mbgl::Color>)mgl_colorPropertyValue {
mbgl::Color color = self.mgl_color;
return {{ color.r, color.g, color.b, color.a }};
}
@end
+
+@implementation NSExpression (MGLColorAdditions)
+
++ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components {
+ if (NSColor *color = [self mgl_colorWithComponentExpressions:components]) {
+ return [NSExpression expressionForConstantValue:color];
+ }
+
+ NSExpression *color = [NSExpression expressionForConstantValue:[NSColor class]];
+ NSExpression *alpha = [NSExpression expressionForConstantValue:@1.0];
+ return [NSExpression expressionForFunction:color
+ selectorName:@"colorWithRed:green:blue:alpha:"
+ arguments:[components arrayByAddingObject:alpha]];
+}
+
++ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components {
+ if (NSColor *color = [self mgl_colorWithComponentExpressions:components]) {
+ return [NSExpression expressionForConstantValue:color];
+ }
+
+ NSExpression *color = [NSExpression expressionForConstantValue:[NSColor class]];
+ return [NSExpression expressionForFunction:color
+ selectorName:@"colorWithRed:green:blue:alpha:"
+ arguments:components];
+}
+
+/**
+ Returns a color object corresponding to the given component expressions.
+ */
++ (NSColor *)mgl_colorWithComponentExpressions:(NSArray<NSExpression *> *)componentExpressions {
+ // Map the component expressions to constant components. If any component is
+ // a non-constant expression, the components cannot be converted into a
+ // constant color value.
+ std::vector<CGFloat> components;
+ for (NSExpression *componentExpression in componentExpressions) {
+ if (componentExpression.expressionType != NSConstantValueExpressionType) {
+ return nil;
+ }
+
+ NSNumber *component = (NSNumber *)componentExpression.constantValue;
+ if (![component isKindOfClass:[NSNumber class]]) {
+ return nil;
+ }
+
+ components.push_back(component.doubleValue / 255.0);
+ }
+ // Alpha
+ components.back() *= 255.0;
+
+ // macOS 10.12 Sierra and below uses calibrated RGB by default.
+ if ([NSColor redColor].colorSpaceName == NSCalibratedRGBColorSpace) {
+ return [NSColor colorWithCalibratedRed:components[0]
+ green:components[1]
+ blue:components[2]
+ alpha:components[3]];
+ }
+ // The Mapbox Style Specification does not specify a color space, but it is
+ // assumed to be sRGB for consistency with CSS.
+ return [NSColor colorWithColorSpace:[NSColorSpace sRGBColorSpace]
+ components:&components[0]
+ count:components.size()];
+}
+
+@end
diff --git a/platform/node/src/node_expression.cpp b/platform/node/src/node_expression.cpp
index 84515060a3..27866ccbed 100644
--- a/platform/node/src/node_expression.cpp
+++ b/platform/node/src/node_expression.cpp
@@ -75,8 +75,8 @@ void NodeExpression::Parse(const Nan::FunctionCallbackInfo<v8::Value>& info) {
auto expr = info[0];
try {
- ParsingContext ctx(expected);
- ParseResult parsed = ctx.parse(mbgl::style::conversion::Convertible(expr));
+ ParsingContext ctx = expected ? ParsingContext(*expected) : ParsingContext();
+ ParseResult parsed = ctx.parseLayerPropertyExpression(mbgl::style::conversion::Convertible(expr));
if (parsed) {
assert(ctx.getErrors().size() == 0);
auto nodeExpr = new NodeExpression(std::move(*parsed));
diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp
index 0fe69e8ac9..9b76f0f542 100644
--- a/platform/node/src/node_map.cpp
+++ b/platform/node/src/node_map.cpp
@@ -74,6 +74,7 @@ void NodeMap::Init(v8::Local<v8::Object> target) {
Nan::SetPrototypeMethod(tpl, "removeLayer", RemoveLayer);
Nan::SetPrototypeMethod(tpl, "addImage", AddImage);
Nan::SetPrototypeMethod(tpl, "removeImage", RemoveImage);
+ Nan::SetPrototypeMethod(tpl, "setLayerZoomRange", SetLayerZoomRange);
Nan::SetPrototypeMethod(tpl, "setLayoutProperty", SetLayoutProperty);
Nan::SetPrototypeMethod(tpl, "setPaintProperty", SetPaintProperty);
Nan::SetPrototypeMethod(tpl, "setFilter", SetFilter);
@@ -740,6 +741,33 @@ void NodeMap::RemoveImage(const Nan::FunctionCallbackInfo<v8::Value>& info) {
nodeMap->map->getStyle().removeImage(*Nan::Utf8String(info[0]));
}
+
+void NodeMap::SetLayerZoomRange(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ using namespace mbgl::style;
+
+ 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]->IsNumber() || !info[2]->IsNumber()) {
+ return Nan::ThrowTypeError("Second and third arguments must be numbers");
+ }
+
+ mbgl::style::Layer* layer = nodeMap->map->getStyle().getLayer(*Nan::Utf8String(info[0]));
+ if (!layer) {
+ return Nan::ThrowTypeError("layer not found");
+ }
+
+ layer->setMinZoom(info[1]->NumberValue());
+ layer->setMaxZoom(info[2]->NumberValue());
+}
void NodeMap::SetLayoutProperty(const Nan::FunctionCallbackInfo<v8::Value>& info) {
using namespace mbgl::style;
diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp
index efa6f6cee0..7fe23ad86a 100644
--- a/platform/node/src/node_map.hpp
+++ b/platform/node/src/node_map.hpp
@@ -50,6 +50,7 @@ public:
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 SetLayerZoomRange(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>&);
diff --git a/platform/node/test/ignores.json b/platform/node/test/ignores.json
index 42751da30f..e0c2475b75 100644
--- a/platform/node/test/ignores.json
+++ b/platform/node/test/ignores.json
@@ -1,4 +1,8 @@
{
+ "query-tests/circle-pitch-scale/viewport-inside-align-map": "https://github.com/mapbox/mapbox-gl-native/issues/10615",
+ "query-tests/circle-pitch-scale/viewport-inside-align-viewport": "https://github.com/mapbox/mapbox-gl-native/issues/10615",
+ "query-tests/edge-cases/box-cutting-antimeridian-z0": "https://github.com/mapbox/mapbox-gl-native/issues/11607",
+ "query-tests/edge-cases/null-island": "https://github.com/mapbox/mapbox-gl-native/issues/11607",
"query-tests/geometry/multilinestring": "needs investigation",
"query-tests/geometry/multipolygon": "needs investigation",
"query-tests/geometry/polygon": "needs investigation",
@@ -25,13 +29,15 @@
"render-tests/geojson/inline-polygon-symbol": "behavior needs reconciliation with gl-js",
"render-tests/mixed-zoom/z10-z11": "https://github.com/mapbox/mapbox-gl-native/issues/10397",
"render-tests/raster-masking/overlapping-zoom": "https://github.com/mapbox/mapbox-gl-native/issues/10195",
+ "render-tests/real-world/bangkok": "https://github.com/mapbox/mapbox-gl-native/issues/10412",
+ "render-tests/real-world/chicago": "https://github.com/mapbox/mapbox-gl-native/issues/10412",
+ "render-tests/real-world/sanfrancisco": "https://github.com/mapbox/mapbox-gl-native/issues/10412",
"render-tests/regressions/mapbox-gl-js#2305": "https://github.com/mapbox/mapbox-gl-native/issues/6927",
"render-tests/regressions/mapbox-gl-js#2467": "https://github.com/mapbox/mapbox-gl-native/issues/10619",
"render-tests/regressions/mapbox-gl-js#2762": "https://github.com/mapbox/mapbox-gl-native/issues/10619",
"render-tests/regressions/mapbox-gl-js#2769": "https://github.com/mapbox/mapbox-gl-native/issues/10619",
"render-tests/regressions/mapbox-gl-js#3682": "https://github.com/mapbox/mapbox-gl-js/issues/3682",
"render-tests/regressions/mapbox-gl-js#5370": "skip - https://github.com/mapbox/mapbox-gl-native/pull/9439",
- "render-tests/regressions/mapbox-gl-js#5599": "https://github.com/mapbox/mapbox-gl-native/issues/10399",
"render-tests/regressions/mapbox-gl-js#5740": "https://github.com/mapbox/mapbox-gl-native/issues/10619",
"render-tests/regressions/mapbox-gl-js#5982": "https://github.com/mapbox/mapbox-gl-native/issues/10619",
"render-tests/regressions/mapbox-gl-native#7357": "https://github.com/mapbox/mapbox-gl-native/issues/7357",
diff --git a/platform/node/test/js/map.test.js b/platform/node/test/js/map.test.js
index 81c15f9c1b..ce22816ef2 100644
--- a/platform/node/test/js/map.test.js
+++ b/platform/node/test/js/map.test.js
@@ -114,6 +114,7 @@ test('Map', function(t) {
'removeLayer',
'addImage',
'removeImage',
+ 'setLayerZoomRange',
'setLayoutProperty',
'setPaintProperty',
'setFilter',
diff --git a/platform/qt/include/qmapbox.hpp b/platform/qt/include/qmapbox.hpp
index 5a5198108c..369890343f 100644
--- a/platform/qt/include/qmapbox.hpp
+++ b/platform/qt/include/qmapbox.hpp
@@ -112,12 +112,16 @@ struct Q_MAPBOXGL_EXPORT CustomLayerRenderParameters {
double zoom;
double bearing;
double pitch;
- double altitude;
+ double fieldOfView;
};
-typedef void (*CustomLayerInitializeFunction)(void* context) ;
-typedef void (*CustomLayerRenderFunction)(void* context, const CustomLayerRenderParameters&);
-typedef void (*CustomLayerDeinitializeFunction)(void* context);
+class Q_MAPBOXGL_EXPORT CustomLayerHostInterface {
+public:
+ virtual ~CustomLayerHostInterface() = default;
+ virtual void initialize() = 0;
+ virtual void render(const CustomLayerRenderParameters&) = 0;
+ virtual void deinitialize() = 0;
+};
} // namespace QMapbox
diff --git a/platform/qt/include/qmapboxgl.hpp b/platform/qt/include/qmapboxgl.hpp
index b5676fbedd..79eb672d1f 100644
--- a/platform/qt/include/qmapboxgl.hpp
+++ b/platform/qt/include/qmapboxgl.hpp
@@ -230,10 +230,7 @@ public:
void removeImage(const QString &name);
void addCustomLayer(const QString &id,
- QMapbox::CustomLayerInitializeFunction,
- QMapbox::CustomLayerRenderFunction,
- QMapbox::CustomLayerDeinitializeFunction,
- void* context,
+ QScopedPointer<QMapbox::CustomLayerHostInterface>& host,
const QString& before = QString());
void addLayer(const QVariantMap &params, const QString& before = QString());
bool layerExists(const QString &id);
diff --git a/platform/qt/src/qmapbox.cpp b/platform/qt/src/qmapbox.cpp
index 1386a4b7aa..2180f22d07 100644
--- a/platform/qt/src/qmapbox.cpp
+++ b/platform/qt/src/qmapbox.cpp
@@ -158,27 +158,9 @@ namespace QMapbox {
*/
/*!
- \typedef QMapbox::CustomLayerDeinitializeFunction
+ \class QMapbox::CustomLayerHostInterface
- Represents a callback to be called when destroying a custom layer.
-
- \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.
-*/
-
-/*!
- \typedef QMapbox::CustomLayerInitializeFunction
-
- Represents a callback to be called when initializing a custom layer.
-
- \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.
-*/
-
-/*!
- \typedef QMapbox::CustomLayerRenderFunction
-
- Represents a callback to be called on each render pass for a custom layer.
+ Represents a host interface to be implemented for rendering custom layers.
\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.
diff --git a/platform/qt/src/qmapboxgl.cpp b/platform/qt/src/qmapboxgl.cpp
index 34fd5509fa..e2c1b31eea 100644
--- a/platform/qt/src/qmapboxgl.cpp
+++ b/platform/qt/src/qmapboxgl.cpp
@@ -1356,20 +1356,43 @@ void QMapboxGL::removeSource(const QString& id)
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,
+ QScopedPointer<QMapbox::CustomLayerHostInterface>& host,
const QString& before)
{
+ class HostWrapper : public mbgl::style::CustomLayerHost {
+ public:
+ QScopedPointer<QMapbox::CustomLayerHostInterface> ptr;
+ HostWrapper(QScopedPointer<QMapbox::CustomLayerHostInterface>& p)
+ : ptr(p.take()) {
+ }
+
+ void initialize() {
+ ptr->initialize();
+ }
+
+ void render(const mbgl::style::CustomLayerRenderParameters& params) {
+ QMapbox::CustomLayerRenderParameters renderParams;
+ renderParams.width = params.width;
+ renderParams.height = params.height;
+ renderParams.latitude = params.latitude;
+ renderParams.longitude = params.longitude;
+ renderParams.zoom = params.zoom;
+ renderParams.bearing = params.bearing;
+ renderParams.pitch = params.pitch;
+ renderParams.fieldOfView = params.fieldOfView;
+ ptr->render(renderParams);
+ }
+
+ void contextLost() { }
+
+ void deinitialize() {
+ ptr->deinitialize();
+ }
+ };
+
d_ptr->mapObj->getStyle().addLayer(std::make_unique<mbgl::style::CustomLayer>(
id.toStdString(),
- reinterpret_cast<mbgl::style::CustomLayerInitializeFunction>(initFn),
- // This cast is safe as long as both mbgl:: and QMapbox::
- // CustomLayerRenderParameters members remains the same.
- (mbgl::style::CustomLayerRenderFunction)renderFn,
- reinterpret_cast<mbgl::style::CustomLayerDeinitializeFunction>(deinitFn),
- context),
+ std::make_unique<HostWrapper>(host)),
before.isEmpty() ? mbgl::optional<std::string>() : mbgl::optional<std::string>(before.toStdString()));
}
diff --git a/src/mbgl/geometry/feature_index.cpp b/src/mbgl/geometry/feature_index.cpp
index 6fb0d5e446..c67786274a 100644
--- a/src/mbgl/geometry/feature_index.cpp
+++ b/src/mbgl/geometry/feature_index.cpp
@@ -17,8 +17,9 @@
namespace mbgl {
-FeatureIndex::FeatureIndex()
- : grid(util::EXTENT, util::EXTENT, util::EXTENT / 16) { // 16x16 grid -> 32px cell
+FeatureIndex::FeatureIndex(std::unique_ptr<const GeometryTileData> tileData_)
+ : grid(util::EXTENT, util::EXTENT, util::EXTENT / 16) // 16x16 grid -> 32px cell
+ , tileData(std::move(tileData_)) {
}
void FeatureIndex::insert(const GeometryCollection& geometries,
@@ -47,12 +48,15 @@ void FeatureIndex::query(
const double tileSize,
const double scale,
const RenderedQueryOptions& queryOptions,
- const GeometryTileData& geometryTileData,
const UnwrappedTileID& tileID,
const std::string& sourceID,
const std::vector<const RenderLayer*>& layers,
const CollisionIndex& collisionIndex,
const float additionalQueryRadius) const {
+
+ if (!tileData) {
+ return;
+ }
// Determine query radius
const float pixelsToTileUnits = util::EXTENT / tileSize / scale;
@@ -72,13 +76,13 @@ void FeatureIndex::query(
if (indexedFeature.sortIndex == previousSortIndex) continue;
previousSortIndex = indexedFeature.sortIndex;
- addFeature(result, indexedFeature, queryGeometry, queryOptions, geometryTileData, tileID.canonical, layers, bearing, pixelsToTileUnits);
+ addFeature(result, indexedFeature, queryGeometry, queryOptions, tileID.canonical, layers, bearing, pixelsToTileUnits);
}
std::vector<IndexedSubfeature> symbolFeatures = collisionIndex.queryRenderedSymbols(queryGeometry, tileID, sourceID);
std::sort(symbolFeatures.begin(), symbolFeatures.end(), topDownSymbols);
for (const auto& symbolFeature : symbolFeatures) {
- addFeature(result, symbolFeature, queryGeometry, queryOptions, geometryTileData, tileID.canonical, layers, bearing, pixelsToTileUnits);
+ addFeature(result, symbolFeature, queryGeometry, queryOptions, tileID.canonical, layers, bearing, pixelsToTileUnits);
}
}
@@ -87,7 +91,6 @@ void FeatureIndex::addFeature(
const IndexedSubfeature& indexedFeature,
const GeometryCoordinates& queryGeometry,
const RenderedQueryOptions& options,
- const GeometryTileData& geometryTileData,
const CanonicalTileID& tileID,
const std::vector<const RenderLayer*>& layers,
const float bearing,
@@ -113,7 +116,7 @@ void FeatureIndex::addFeature(
}
if (!geometryTileFeature) {
- sourceLayer = geometryTileData.getLayer(indexedFeature.sourceLayerName);
+ sourceLayer = tileData->getLayer(indexedFeature.sourceLayerName);
assert(sourceLayer);
geometryTileFeature = sourceLayer->getFeature(indexedFeature.index);
diff --git a/src/mbgl/geometry/feature_index.hpp b/src/mbgl/geometry/feature_index.hpp
index e95bb94da6..9e0c172342 100644
--- a/src/mbgl/geometry/feature_index.hpp
+++ b/src/mbgl/geometry/feature_index.hpp
@@ -50,8 +50,10 @@ public:
class FeatureIndex {
public:
- FeatureIndex();
+ FeatureIndex(std::unique_ptr<const GeometryTileData> tileData_);
+ const GeometryTileData* getData() { return tileData.get(); }
+
void insert(const GeometryCollection&, std::size_t index, const std::string& sourceLayerName, const std::string& bucketName);
void query(
@@ -61,7 +63,6 @@ public:
const double tileSize,
const double scale,
const RenderedQueryOptions& options,
- const GeometryTileData&,
const UnwrappedTileID&,
const std::string&,
const std::vector<const RenderLayer*>&,
@@ -83,7 +84,6 @@ private:
const IndexedSubfeature&,
const GeometryCoordinates& queryGeometry,
const RenderedQueryOptions& options,
- const GeometryTileData&,
const CanonicalTileID&,
const std::vector<const RenderLayer*>&,
const float bearing,
@@ -93,5 +93,6 @@ private:
unsigned int sortIndex = 0;
std::unordered_map<std::string, std::vector<std::string>> bucketLayerIDs;
+ std::unique_ptr<const GeometryTileData> tileData;
};
} // namespace mbgl
diff --git a/src/mbgl/layout/symbol_instance.cpp b/src/mbgl/layout/symbol_instance.cpp
index 6e152349ca..7dfa8edf43 100644
--- a/src/mbgl/layout/symbol_instance.cpp
+++ b/src/mbgl/layout/symbol_instance.cpp
@@ -27,7 +27,7 @@ SymbolInstance::SymbolInstance(Anchor& anchor_,
anchor(anchor_),
line(line_),
index(index_),
- hasText(shapedTextOrientations.first || shapedTextOrientations.second),
+ hasText(false),
hasIcon(shapedIcon),
// Create the collision features that will be used to check whether this symbol instance can be placed
@@ -48,6 +48,8 @@ SymbolInstance::SymbolInstance(Anchor& anchor_,
if (shapedTextOrientations.second) {
verticalGlyphQuads = getGlyphQuads(shapedTextOrientations.second, layout, textPlacement, positions);
}
+ // 'hasText' depends on finding at least one glyph in the shaping that's also in the GlyphPositionMap
+ hasText = horizontalGlyphQuads.size() > 0 || verticalGlyphQuads.size() > 0;
if (shapedTextOrientations.first && shapedTextOrientations.second) {
writingModes = WritingModeType::Horizontal | WritingModeType::Vertical;
diff --git a/src/mbgl/layout/symbol_layout.cpp b/src/mbgl/layout/symbol_layout.cpp
index 3bf85407c6..82a9255824 100644
--- a/src/mbgl/layout/symbol_layout.cpp
+++ b/src/mbgl/layout/symbol_layout.cpp
@@ -126,7 +126,7 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
if (hasText) {
std::string u8string = layout.evaluate<TextField>(zoom, ft);
- if (layout.get<TextField>().isConstant()) {
+ if (layout.get<TextField>().isConstant() && !leader.layout.get<TextField>().isExpression()) {
u8string = util::replaceTokens(u8string, getValue);
}
@@ -159,7 +159,7 @@ SymbolLayout::SymbolLayout(const BucketParameters& parameters,
if (hasIcon) {
std::string icon = layout.evaluate<IconImage>(zoom, ft);
- if (layout.get<IconImage>().isConstant()) {
+ if (layout.get<IconImage>().isConstant() && !leader.layout.get<IconImage>().isExpression()) {
icon = util::replaceTokens(icon, getValue);
}
ft.icon = icon;
diff --git a/src/mbgl/layout/symbol_projection.cpp b/src/mbgl/layout/symbol_projection.cpp
index 9e077e2532..ef669c6e19 100644
--- a/src/mbgl/layout/symbol_projection.cpp
+++ b/src/mbgl/layout/symbol_projection.cpp
@@ -240,7 +240,11 @@ namespace mbgl {
const PlacedSymbol& symbol,
const mat4& labelPlaneMatrix,
const bool returnTileDistance) {
-
+ if (symbol.glyphOffsets.empty()) {
+ assert(false);
+ return optional<std::pair<PlacedGlyph, PlacedGlyph>>();
+ }
+
const float firstGlyphOffset = symbol.glyphOffsets.front();
const float lastGlyphOffset = symbol.glyphOffsets.back();;
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index 525291a628..d81544eed5 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -446,7 +446,6 @@ CameraOptions Map::cameraForGeometry(const Geometry<double>& geometry, const Edg
latLngs.push_back({ pt.y, pt.x });
});
return cameraForLatLngs(latLngs, padding, bearing);
-
}
LatLngBounds Map::latLngBoundsForCamera(const CameraOptions& camera) const {
diff --git a/src/mbgl/programs/symbol_program.hpp b/src/mbgl/programs/symbol_program.hpp
index a14afac702..9b5037ed9f 100644
--- a/src/mbgl/programs/symbol_program.hpp
+++ b/src/mbgl/programs/symbol_program.hpp
@@ -61,8 +61,8 @@ struct SymbolLayoutAttributes : gl::Attributes<
{{
static_cast<int16_t>(labelAnchor.x),
static_cast<int16_t>(labelAnchor.y),
- static_cast<int16_t>(::round(o.x * 64)), // use 1/64 pixels for placement
- static_cast<int16_t>(::round((o.y + glyphOffsetY) * 64))
+ static_cast<int16_t>(::round(o.x * 32)), // use 1/32 pixels for placement
+ static_cast<int16_t>(::round((o.y + glyphOffsetY) * 32))
}},
{{
tx,
diff --git a/src/mbgl/renderer/layers/render_custom_layer.cpp b/src/mbgl/renderer/layers/render_custom_layer.cpp
index a429b8d82e..be9f64d9eb 100644
--- a/src/mbgl/renderer/layers/render_custom_layer.cpp
+++ b/src/mbgl/renderer/layers/render_custom_layer.cpp
@@ -6,23 +6,24 @@
#include <mbgl/style/layers/custom_layer_impl.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/gl/gl.hpp>
+#include <mbgl/util/mat4.hpp>
namespace mbgl {
using namespace style;
RenderCustomLayer::RenderCustomLayer(Immutable<style::CustomLayer::Impl> _impl)
- : RenderLayer(LayerType::Custom, _impl) {
+ : RenderLayer(LayerType::Custom, _impl), host(_impl->host) {
+ assert(BackendScope::exists());
+ host->initialize();
}
RenderCustomLayer::~RenderCustomLayer() {
assert(BackendScope::exists());
- if (initialized) {
- if (contextDestroyed && impl().contextLostFn ) {
- impl().contextLostFn(impl().context);
- } else if (!contextDestroyed && impl().deinitializeFn) {
- impl().deinitializeFn(impl().context);
- }
+ if (contextDestroyed) {
+ host->contextLost();
+ } else {
+ host->deinitialize();
}
}
@@ -44,15 +45,13 @@ std::unique_ptr<Bucket> RenderCustomLayer::createBucket(const BucketParameters&,
}
void RenderCustomLayer::render(PaintParameters& paintParameters, RenderSource*) {
- if (context != impl().context || !initialized) {
+ if (host != impl().host) {
//If the context changed, deinitialize the previous one before initializing the new one.
- if (context && !contextDestroyed && impl().deinitializeFn) {
- MBGL_CHECK_ERROR(impl().deinitializeFn(context));
+ if (host && !contextDestroyed) {
+ MBGL_CHECK_ERROR(host->deinitialize());
}
- context = impl().context;
- assert(impl().initializeFn);
- MBGL_CHECK_ERROR(impl().initializeFn(impl().context));
- initialized = true;
+ host = impl().host;
+ MBGL_CHECK_ERROR(host->initialize());
}
gl::Context& glContext = paintParameters.context;
@@ -74,9 +73,11 @@ void RenderCustomLayer::render(PaintParameters& paintParameters, RenderSource*)
parameters.bearing = -state.getAngle() * util::RAD2DEG;
parameters.pitch = state.getPitch();
parameters.fieldOfView = state.getFieldOfView();
+ mat4 projMatrix;
+ state.getProjMatrix(projMatrix);
+ parameters.projectionMatrix = projMatrix;
- assert(impl().renderFn);
- MBGL_CHECK_ERROR(impl().renderFn(context, parameters));
+ MBGL_CHECK_ERROR(host->render(parameters));
// Reset the view back to our original one, just in case the CustomLayer changed
// the viewport or Framebuffer.
diff --git a/src/mbgl/renderer/layers/render_custom_layer.hpp b/src/mbgl/renderer/layers/render_custom_layer.hpp
index 6d1fea99d3..971d8d8f42 100644
--- a/src/mbgl/renderer/layers/render_custom_layer.hpp
+++ b/src/mbgl/renderer/layers/render_custom_layer.hpp
@@ -24,9 +24,8 @@ public:
};
private:
- bool initialized = false;
bool contextDestroyed = false;
- void * context = nullptr;
+ std::shared_ptr<style::CustomLayerHost> host;
};
template <>
diff --git a/src/mbgl/shaders/collision_box.cpp b/src/mbgl/shaders/collision_box.cpp
index 9d11640bf4..bc5d9bc6f9 100644
--- a/src/mbgl/shaders/collision_box.cpp
+++ b/src/mbgl/shaders/collision_box.cpp
@@ -22,7 +22,10 @@ varying float v_notUsed;
void main() {
vec4 projectedPoint = u_matrix * vec4(a_anchor_pos, 0, 1);
highp float camera_to_anchor_distance = projectedPoint.w;
- highp float collision_perspective_ratio = 0.5 + 0.5 * (u_camera_to_center_distance / camera_to_anchor_distance);
+ highp float collision_perspective_ratio = clamp(
+ 0.5 + 0.5 * (u_camera_to_center_distance / camera_to_anchor_distance),
+ 0.0, // Prevents oversized near-field boxes in pitched/overzoomed tiles
+ 4.0);
gl_Position = u_matrix * vec4(a_pos, 0.0, 1.0);
gl_Position.xy += a_extrude * u_extrude_scale * gl_Position.w * collision_perspective_ratio;
diff --git a/src/mbgl/shaders/line_pattern.cpp b/src/mbgl/shaders/line_pattern.cpp
index f8d785ade9..be88255e3c 100644
--- a/src/mbgl/shaders/line_pattern.cpp
+++ b/src/mbgl/shaders/line_pattern.cpp
@@ -215,8 +215,14 @@ void main() {
float x_a = mod(v_linesofar / u_pattern_size_a.x, 1.0);
float x_b = mod(v_linesofar / u_pattern_size_b.x, 1.0);
- float y_a = 0.5 + (v_normal.y * v_width2.s / u_pattern_size_a.y);
- float y_b = 0.5 + (v_normal.y * v_width2.s / u_pattern_size_b.y);
+
+ // v_normal.y is 0 at the midpoint of the line, -1 at the lower edge, 1 at the upper edge
+ // we clamp the line width outset to be between 0 and half the pattern height plus padding (2.0)
+ // to ensure we don't sample outside the designated symbol on the sprite sheet.
+ // 0.5 is added to shift the component to be bounded between 0 and 1 for interpolation of
+ // the texture coordinate
+ float y_a = 0.5 + (v_normal.y * clamp(v_width2.s, 0.0, (u_pattern_size_a.y + 2.0) / 2.0) / u_pattern_size_a.y);
+ float y_b = 0.5 + (v_normal.y * clamp(v_width2.s, 0.0, (u_pattern_size_b.y + 2.0) / 2.0) / u_pattern_size_b.y);
vec2 pos_a = mix(u_pattern_tl_a / u_texsize, u_pattern_br_a / u_texsize, vec2(x_a, y_a));
vec2 pos_b = mix(u_pattern_tl_b / u_texsize, u_pattern_br_b / u_texsize, vec2(x_b, y_b));
diff --git a/src/mbgl/shaders/symbol_icon.cpp b/src/mbgl/shaders/symbol_icon.cpp
index f5c2bbe22d..c037c81005 100644
--- a/src/mbgl/shaders/symbol_icon.cpp
+++ b/src/mbgl/shaders/symbol_icon.cpp
@@ -80,7 +80,10 @@ void main() {
highp float distance_ratio = u_pitch_with_map ?
camera_to_anchor_distance / u_camera_to_center_distance :
u_camera_to_center_distance / camera_to_anchor_distance;
- highp float perspective_ratio = 0.5 + 0.5 * distance_ratio;
+ highp float perspective_ratio = clamp(
+ 0.5 + 0.5 * distance_ratio,
+ 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
+ 4.0);
size *= perspective_ratio;
@@ -102,7 +105,7 @@ void main() {
mat2 rotation_matrix = mat2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);
vec4 projected_pos = u_label_plane_matrix * vec4(a_projected_pos.xy, 0.0, 1.0);
- gl_Position = u_gl_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 64.0 * fontScale), 0.0, 1.0);
+ gl_Position = u_gl_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 32.0 * fontScale), 0.0, 1.0);
v_tex = a_tex / u_texsize;
vec2 fade_opacity = unpack_opacity(a_fade_opacity);
diff --git a/src/mbgl/shaders/symbol_sdf.cpp b/src/mbgl/shaders/symbol_sdf.cpp
index 441eaf7aac..b584c00315 100644
--- a/src/mbgl/shaders/symbol_sdf.cpp
+++ b/src/mbgl/shaders/symbol_sdf.cpp
@@ -156,7 +156,10 @@ void main() {
highp float distance_ratio = u_pitch_with_map ?
camera_to_anchor_distance / u_camera_to_center_distance :
u_camera_to_center_distance / camera_to_anchor_distance;
- highp float perspective_ratio = 0.5 + 0.5 * distance_ratio;
+ highp float perspective_ratio = clamp(
+ 0.5 + 0.5 * distance_ratio,
+ 0.0, // Prevents oversized near-field symbols in pitched/overzoomed tiles
+ 4.0);
size *= perspective_ratio;
@@ -180,7 +183,7 @@ void main() {
mat2 rotation_matrix = mat2(angle_cos, -1.0 * angle_sin, angle_sin, angle_cos);
vec4 projected_pos = u_label_plane_matrix * vec4(a_projected_pos.xy, 0.0, 1.0);
- gl_Position = u_gl_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 64.0 * fontScale), 0.0, 1.0);
+ gl_Position = u_gl_coord_matrix * vec4(projected_pos.xy / projected_pos.w + rotation_matrix * (a_offset / 32.0 * fontScale), 0.0, 1.0);
float gamma_scale = gl_Position.w;
vec2 tex = a_tex / u_texsize;
diff --git a/src/mbgl/style/conversion/filter.cpp b/src/mbgl/style/conversion/filter.cpp
index fba149da12..3c941945fd 100644
--- a/src/mbgl/style/conversion/filter.cpp
+++ b/src/mbgl/style/conversion/filter.cpp
@@ -2,7 +2,7 @@
#include <mbgl/util/geometry.hpp>
#include <mbgl/style/expression/expression.hpp>
#include <mbgl/style/expression/type.hpp>
-#include <mbgl/style/conversion/expression.hpp>
+#include <mbgl/style/expression/parsing_context.hpp>
namespace mbgl {
namespace style {
@@ -236,10 +236,13 @@ optional<Filter> convertCompoundFilter(const Convertible& value, Error& error) {
}
optional<Filter> convertExpressionFilter(const Convertible& value, Error& error) {
- optional<std::unique_ptr<Expression>> expression = convert<std::unique_ptr<Expression>>(value, error, expression::type::Boolean);
+ expression::ParsingContext ctx(expression::type::Boolean);
+ expression::ParseResult expression = ctx.parseExpression(value);
if (!expression) {
+ error = { ctx.getCombinedErrors() };
return {};
}
+
return { ExpressionFilter { std::move(*expression) } };
}
diff --git a/src/mbgl/style/conversion/stringify.hpp b/src/mbgl/style/conversion/stringify.hpp
index 7924a442c4..7b7727d7c4 100644
--- a/src/mbgl/style/conversion/stringify.hpp
+++ b/src/mbgl/style/conversion/stringify.hpp
@@ -290,138 +290,19 @@ void stringify(Writer& writer, const Undefined&) {
writer.Null();
}
-template <class Writer>
-void stringify(Writer& writer, const CategoricalValue& v) {
- CategoricalValue::visit(v, [&] (const auto& v_) { stringify(writer, v_); });
-}
-
-template <class Writer>
-class StringifyStops {
-public:
- Writer& writer;
-
- template <class T>
- void operator()(const ExponentialStops<T>& f) {
- writer.Key("type");
- writer.String("exponential");
- writer.Key("base");
- writer.Double(f.base);
- writer.Key("stops");
- stringifyStops(f.stops);
- }
-
- template <class T>
- void operator()(const IntervalStops<T>& f) {
- writer.Key("type");
- writer.String("interval");
- writer.Key("stops");
- stringifyStops(f.stops);
- }
-
- template <class T>
- void operator()(const CategoricalStops<T>& f) {
- writer.Key("type");
- writer.String("categorical");
- writer.Key("stops");
- stringifyStops(f.stops);
- }
-
- template <class T>
- void operator()(const IdentityStops<T>&) {
- writer.Key("type");
- writer.String("identity");
- }
-
- template <class T>
- void operator()(const CompositeExponentialStops<T>& f) {
- writer.Key("type");
- writer.String("exponential");
- writer.Key("base");
- writer.Double(f.base);
- writer.Key("stops");
- stringifyCompositeStops(f.stops);
- }
-
- template <class T>
- void operator()(const CompositeIntervalStops<T>& f) {
- writer.Key("type");
- writer.String("interval");
- writer.Key("stops");
- stringifyCompositeStops(f.stops);
- }
-
- template <class T>
- void operator()(const CompositeCategoricalStops<T>& f) {
- writer.Key("type");
- writer.String("categorical");
- writer.Key("stops");
- stringifyCompositeStops(f.stops);
- }
-
-private:
- template <class K, class V>
- void stringifyStops(const std::map<K, V>& stops) {
- writer.StartArray();
- for (const auto& stop : stops) {
- writer.StartArray();
- stringify(writer, stop.first);
- stringify(writer, stop.second);
- writer.EndArray();
- }
- writer.EndArray();
- }
-
- template <class InnerStops>
- void stringifyCompositeStops(const std::map<float, InnerStops>& stops) {
- writer.StartArray();
- for (const auto& outer : stops) {
- for (const auto& inner : outer.second) {
- writer.StartArray();
- writer.StartObject();
- writer.Key("zoom");
- writer.Double(outer.first);
- writer.Key("value");
- stringify(writer, inner.first);
- writer.EndObject();
- stringify(writer, inner.second);
- writer.EndArray();
- }
- }
- writer.EndArray();
- }
-};
-
template <class Writer, class T>
-void stringify(Writer& writer, const CameraFunction<T>& f) {
- writer.StartObject();
- CameraFunction<T>::Stops::visit(f.stops, StringifyStops<Writer> { writer });
- writer.EndObject();
+void stringify(Writer& writer, const CameraFunction<T>& fn) {
+ stringify(writer, fn.getExpression().serialize());
}
template <class Writer, class T>
-void stringify(Writer& writer, const SourceFunction<T>& f) {
- writer.StartObject();
- writer.Key("property");
- writer.String(f.property);
- SourceFunction<T>::Stops::visit(f.stops, StringifyStops<Writer> { writer });
- if (f.defaultValue) {
- writer.Key("default");
- stringify(writer, *f.defaultValue);
- }
- writer.EndObject();
+void stringify(Writer& writer, const SourceFunction<T>& fn) {
+ stringify(writer, fn.getExpression().serialize());
}
template <class Writer, class T>
-void stringify(Writer& writer, const CompositeFunction<T>& f) {
- writer.StartObject();
- writer.Key("property");
- writer.String(f.property);
- CompositeFunction<T>::Stops::visit(f.stops, StringifyStops<Writer> { writer });
- if (f.defaultValue) {
- writer.Key("default");
- stringify(writer, *f.defaultValue);
- }
- writer.EndObject();
+void stringify(Writer& writer, const CompositeFunction<T>& fn) {
+ stringify(writer, fn.getExpression().serialize());
}
template <class Writer, class T>
diff --git a/src/mbgl/style/expression/at.cpp b/src/mbgl/style/expression/at.cpp
index e447d33bc7..725e5ddb51 100644
--- a/src/mbgl/style/expression/at.cpp
+++ b/src/mbgl/style/expression/at.cpp
@@ -19,15 +19,21 @@ EvaluationResult At::evaluate(const EvaluationContext& params) const {
const auto i = evaluatedIndex->get<double>();
const auto inputArray = evaluatedInput->get<std::vector<Value>>();
- if (i < 0 || i >= inputArray.size()) {
+ if (i < 0) {
return EvaluationError {
- "Array index out of bounds: " + stringify(i) +
- " > " + util::toString(inputArray.size()) + "."
+ "Array index out of bounds: " + util::toString(i) + " < 0."
+ };
+ }
+
+ if (i >= inputArray.size()) {
+ return EvaluationError {
+ "Array index out of bounds: " + util::toString(i) +
+ " > " + util::toString(inputArray.size() - 1) + "."
};
}
if (i != std::floor(i)) {
return EvaluationError {
- "Array index must be an integer, but found " + stringify(i) + " instead."
+ "Array index must be an integer, but found " + util::toString(i) + " instead."
};
}
return inputArray[static_cast<std::size_t>(i)];
diff --git a/src/mbgl/style/expression/compound_expression.cpp b/src/mbgl/style/expression/compound_expression.cpp
index 86d968c521..c36ffa33e3 100644
--- a/src/mbgl/style/expression/compound_expression.cpp
+++ b/src/mbgl/style/expression/compound_expression.cpp
@@ -6,6 +6,7 @@
#include <mbgl/util/ignore.hpp>
#include <mbgl/util/string.hpp>
#include <mbgl/util/platform.hpp>
+#include <cmath>
namespace mbgl {
namespace style {
@@ -209,12 +210,7 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
);
});
define("to-rgba", [](const Color& color) -> Result<std::array<double, 4>> {
- return std::array<double, 4> {{
- 255 * color.r / color.a,
- 255 * color.g / color.a,
- 255 * color.b / color.a,
- color.a
- }};
+ return color.toArray();
});
define("rgba", rgba);
@@ -271,13 +267,6 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
return object.at(key);
});
- define("length", [](const std::vector<Value>& arr) -> Result<double> {
- return arr.size();
- });
- define("length", [] (const std::string s) -> Result<double> {
- return s.size();
- });
-
define("properties", [](const EvaluationContext& params) -> Result<std::unordered_map<std::string, Value>> {
if (!params.feature) {
return EvaluationError {
@@ -374,6 +363,11 @@ std::unordered_map<std::string, CompoundExpressionRegistry::Definition> initiali
return result;
});
+ define("round", [](double x) -> Result<double> { return std::round(x); });
+ define("floor", [](double x) -> Result<double> { return std::floor(x); });
+ define("ceil", [](double x) -> Result<double> { return std::ceil(x); });
+ define("abs", [](double x) -> Result<double> { return std::abs(x); });
+
define(">", [](double lhs, double rhs) -> Result<bool> { return lhs > rhs; });
define(">", [](const std::string& lhs, const std::string& rhs) -> Result<bool> { return lhs > rhs; });
define(">=", [](double lhs, double rhs) -> Result<bool> { return lhs >= rhs; });
diff --git a/src/mbgl/style/expression/interpolate.cpp b/src/mbgl/style/expression/interpolate.cpp
index 30b2cba81b..daad8523f2 100644
--- a/src/mbgl/style/expression/interpolate.cpp
+++ b/src/mbgl/style/expression/interpolate.cpp
@@ -223,7 +223,11 @@ mbgl::Value Interpolate<T>::serialize() const {
interpolator.match(
[&](const ExponentialInterpolator& exponential) {
- serialized.emplace_back(std::vector<mbgl::Value>{{ std::string("exponential"), exponential.base }});
+ if (exponential.base == 1) {
+ serialized.emplace_back(std::vector<mbgl::Value>{{ std::string("linear") }});
+ } else {
+ serialized.emplace_back(std::vector<mbgl::Value>{{ std::string("exponential"), exponential.base }});
+ }
},
[&](const CubicBezierInterpolator& cubicBezier) {
static const std::string cubicBezierTag("cubic-bezier");
diff --git a/src/mbgl/style/expression/length.cpp b/src/mbgl/style/expression/length.cpp
new file mode 100644
index 0000000000..258353ae4e
--- /dev/null
+++ b/src/mbgl/style/expression/length.cpp
@@ -0,0 +1,66 @@
+#include <mbgl/style/expression/length.hpp>
+#include <mbgl/util/string.hpp>
+
+namespace mbgl {
+namespace style {
+namespace expression {
+
+Length::Length(std::unique_ptr<Expression> input_)
+ : Expression(type::Number),
+ input(std::move(input_)) {
+}
+
+EvaluationResult Length::evaluate(const EvaluationContext& params) const {
+ const EvaluationResult value = input->evaluate(params);
+ if (!value) return value;
+ return value->match(
+ [] (const std::string& s) {
+ return EvaluationResult { double(s.size()) };
+ },
+ [] (const std::vector<Value>& v) {
+ return EvaluationResult { double(v.size()) };
+ },
+ [&] (const auto&) -> EvaluationResult {
+ return EvaluationError { "Expected value to be of type string or array, but found " + toString(typeOf(*value)) + " instead." };
+ });
+}
+
+void Length::eachChild(const std::function<void(const Expression&)>& visit) const {
+ visit(*input);
+}
+
+bool Length::operator==(const Expression& e) const {
+ if (auto eq = dynamic_cast<const Length*>(&e)) {
+ return *eq->input == *input;
+ }
+ return false;
+}
+
+std::vector<optional<Value>> Length::possibleOutputs() const {
+ return { nullopt };
+}
+
+using namespace mbgl::style::conversion;
+ParseResult Length::parse(const Convertible& value, ParsingContext& ctx) {
+ std::size_t length = arrayLength(value);
+
+ if (length != 2) {
+ ctx.error("Expected one argument, but found " + util::toString(length) + " instead.");
+ return ParseResult();
+ }
+
+ ParseResult input = ctx.parse(arrayMember(value, 1), 1);
+ if (!input) return ParseResult();
+
+ type::Type type = (*input)->getType();
+ if (!type.is<type::Array>() && !type.is<type::StringType>() && !type.is<type::ValueType>()) {
+ ctx.error("Expected argument of type string or array, but found " + toString(type) + " instead.");
+ return ParseResult();
+ }
+
+ return ParseResult(std::make_unique<Length>(std::move(*input)));
+}
+
+} // namespace expression
+} // namespace style
+} // namespace mbgl
diff --git a/src/mbgl/style/expression/parsing_context.cpp b/src/mbgl/style/expression/parsing_context.cpp
index 0215982209..b522aeff9a 100644
--- a/src/mbgl/style/expression/parsing_context.cpp
+++ b/src/mbgl/style/expression/parsing_context.cpp
@@ -15,6 +15,7 @@
#include <mbgl/style/expression/compound_expression.hpp>
#include <mbgl/style/expression/equals.hpp>
#include <mbgl/style/expression/interpolate.hpp>
+#include <mbgl/style/expression/length.hpp>
#include <mbgl/style/expression/let.hpp>
#include <mbgl/style/expression/literal.hpp>
#include <mbgl/style/expression/match.hpp>
@@ -31,23 +32,36 @@ namespace style {
namespace expression {
bool isConstant(const Expression& expression) {
- if (dynamic_cast<const Var*>(&expression)) {
- return false;
+ if (auto varExpression = dynamic_cast<const Var*>(&expression)) {
+ return isConstant(*varExpression->getBoundExpression());
}
-
+
if (auto compound = dynamic_cast<const CompoundExpressionBase*>(&expression)) {
if (compound->getName() == "error") {
return false;
}
}
+
+ bool isTypeAnnotation = dynamic_cast<const Coercion*>(&expression) ||
+ dynamic_cast<const Assertion*>(&expression) ||
+ dynamic_cast<const ArrayAssertion*>(&expression);
- bool literalArgs = true;
+ bool childrenConstant = true;
expression.eachChild([&](const Expression& child) {
- if (!dynamic_cast<const Literal*>(&child)) {
- literalArgs = false;
+ // We can _almost_ assume that if `expressions` children are constant,
+ // they would already have been evaluated to Literal values when they
+ // were parsed. Type annotations are the exception, because they might
+ // have been inferred and added after a child was parsed.
+
+ // So we recurse into isConstant() for the children of type annotations,
+ // but otherwise simply check whether they are Literals.
+ if (isTypeAnnotation) {
+ childrenConstant = childrenConstant && isConstant(child);
+ } else {
+ childrenConstant = childrenConstant && dynamic_cast<const Literal*>(&child);
}
});
- if (!literalArgs) {
+ if (!childrenConstant) {
return false;
}
@@ -89,6 +103,7 @@ const ExpressionRegistry& getExpressionRegistry() {
{"case", Case::parse},
{"coalesce", Coalesce::parse},
{"interpolate", parseInterpolate},
+ {"length", Length::parse},
{"let", Let::parse},
{"literal", Literal::parse},
{"match", parseMatch},
@@ -139,15 +154,15 @@ ParseResult ParsingContext::parse(const Convertible& value, TypeAnnotationOption
return parsed;
}
- if (expected) {
- auto array = [&](std::unique_ptr<Expression> expression) {
- std::vector<std::unique_ptr<Expression>> args;
- args.push_back(std::move(expression));
- return args;
- };
+ auto array = [&](std::unique_ptr<Expression> expression) {
+ std::vector<std::unique_ptr<Expression>> args;
+ args.push_back(std::move(expression));
+ return args;
+ };
+ if (expected) {
const type::Type actual = (*parsed)->getType();
- if ((*expected == type::String || *expected == type::Number || *expected == type::Boolean) && actual == type::Value) {
+ if ((*expected == type::String || *expected == type::Number || *expected == type::Boolean || *expected == type::Object) && actual == type::Value) {
if (typeAnnotationOption == includeTypeAnnotations) {
parsed = { std::make_unique<Assertion>(*expected, array(std::move(*parsed))) };
}
@@ -167,7 +182,7 @@ ParseResult ParsingContext::parse(const Convertible& value, TypeAnnotationOption
}
}
- // If an expression's arguments are all literals, we can evaluate
+ // If an expression's arguments are all constant, we can evaluate
// it immediately and replace it with a literal value in the
// parsed result.
if (!dynamic_cast<Literal *>(parsed->get()) && isConstant(**parsed)) {
@@ -191,8 +206,16 @@ ParseResult ParsingContext::parse(const Convertible& value, TypeAnnotationOption
}
}
- // if this is the root expression, enforce constraints on the use ["zoom"].
- if (key.size() == 0 && !isZoomConstant(**parsed)) {
+ return parsed;
+}
+
+ParseResult ParsingContext::parseExpression(const Convertible& value, TypeAnnotationOption typeAnnotationOption) {
+ return parse(value, typeAnnotationOption);
+}
+
+ParseResult ParsingContext::parseLayerPropertyExpression(const Convertible& value, TypeAnnotationOption typeAnnotationOption) {
+ ParseResult parsed = parse(value, typeAnnotationOption);
+ if (parsed && !isZoomConstant(**parsed)) {
optional<variant<const InterpolateBase*, const Step*, ParsingError>> zoomCurve = findZoomCurve(parsed->get());
if (!zoomCurve) {
error(R"("zoom" expression may only be used as input to a top-level "step" or "interpolate" expression.)");
@@ -202,10 +225,23 @@ ParseResult ParsingContext::parse(const Convertible& value, TypeAnnotationOption
return ParseResult();
}
}
-
return parsed;
}
+const std::string ParsingContext::getCombinedErrors() const {
+ std::string combinedError;
+ for (const ParsingError& parsingError : *errors) {
+ if (combinedError.size() > 0) {
+ combinedError += "\n";
+ }
+ if (parsingError.key.size() > 0) {
+ combinedError += parsingError.key + ": ";
+ }
+ combinedError += parsingError.message;
+ }
+ return combinedError;
+}
+
optional<std::string> ParsingContext::checkType(const type::Type& t) {
assert(expected);
optional<std::string> err = type::checkSubtype(*expected, t);
diff --git a/src/mbgl/style/expression/value.cpp b/src/mbgl/style/expression/value.cpp
index 72779d4956..1b3257c755 100644
--- a/src/mbgl/style/expression/value.cpp
+++ b/src/mbgl/style/expression/value.cpp
@@ -106,12 +106,13 @@ Value ValueConverter<mbgl::Value>::toExpressionValue(const mbgl::Value& value) {
mbgl::Value ValueConverter<mbgl::Value>::fromExpressionValue(const Value& value) {
return value.match(
[&](const Color& color)->mbgl::Value {
+ std::array<double, 4> array = color.toArray();
return std::vector<mbgl::Value>{
std::string("rgba"),
- double(255 * color.r / color.a),
- double(255 * color.g / color.a),
- double(255 * color.b / color.a),
- double(color.a)
+ array[0],
+ array[1],
+ array[2],
+ array[3],
};
},
[&](const std::vector<Value>& values)->mbgl::Value {
diff --git a/src/mbgl/style/layers/background_layer.cpp b/src/mbgl/style/layers/background_layer.cpp
index d4ead18816..66ab46c078 100644
--- a/src/mbgl/style/layers/background_layer.cpp
+++ b/src/mbgl/style/layers/background_layer.cpp
@@ -53,12 +53,14 @@ void BackgroundLayer::setMinZoom(float minZoom) {
auto impl_ = mutableImpl();
impl_->minZoom = minZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
void BackgroundLayer::setMaxZoom(float maxZoom) {
auto impl_ = mutableImpl();
impl_->maxZoom = maxZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
// Layout properties
diff --git a/src/mbgl/style/layers/circle_layer.cpp b/src/mbgl/style/layers/circle_layer.cpp
index 9854932699..6dd744df1f 100644
--- a/src/mbgl/style/layers/circle_layer.cpp
+++ b/src/mbgl/style/layers/circle_layer.cpp
@@ -81,12 +81,14 @@ void CircleLayer::setMinZoom(float minZoom) {
auto impl_ = mutableImpl();
impl_->minZoom = minZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
void CircleLayer::setMaxZoom(float maxZoom) {
auto impl_ = mutableImpl();
impl_->maxZoom = maxZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
// Layout properties
diff --git a/src/mbgl/style/layers/custom_layer.cpp b/src/mbgl/style/layers/custom_layer.cpp
index 854c771847..0e51a70e50 100644
--- a/src/mbgl/style/layers/custom_layer.cpp
+++ b/src/mbgl/style/layers/custom_layer.cpp
@@ -6,20 +6,8 @@ namespace mbgl {
namespace style {
CustomLayer::CustomLayer(const std::string& layerID,
- CustomLayerInitializeFunction init,
- CustomLayerRenderFunction render,
- CustomLayerContextLostFunction contextLost,
- CustomLayerDeinitializeFunction deinit,
- void* context)
- : Layer(makeMutable<Impl>(layerID, init, render, contextLost, deinit, context)) {
-}
-
-CustomLayer::CustomLayer(const std::string& layerID,
- CustomLayerInitializeFunction init,
- CustomLayerRenderFunction render,
- CustomLayerDeinitializeFunction deinit,
- void* context)
- : Layer(makeMutable<Impl>(layerID, init, render, nullptr, deinit, context)) {
+ std::unique_ptr<CustomLayerHost> host)
+ : Layer(makeMutable<Impl>(layerID, std::move(host))) {
}
CustomLayer::~CustomLayer() = default;
diff --git a/src/mbgl/style/layers/custom_layer_impl.cpp b/src/mbgl/style/layers/custom_layer_impl.cpp
index 1de268d2e2..05c41623c4 100644
--- a/src/mbgl/style/layers/custom_layer_impl.cpp
+++ b/src/mbgl/style/layers/custom_layer_impl.cpp
@@ -4,17 +4,9 @@ namespace mbgl {
namespace style {
CustomLayer::Impl::Impl(const std::string& id_,
- CustomLayerInitializeFunction initializeFn_,
- CustomLayerRenderFunction renderFn_,
- CustomLayerContextLostFunction contextLostFn_,
- CustomLayerDeinitializeFunction deinitializeFn_,
- void* context_)
+ std::unique_ptr<CustomLayerHost> host_)
: Layer::Impl(LayerType::Custom, id_, std::string()) {
- initializeFn = initializeFn_;
- renderFn = renderFn_;
- deinitializeFn = deinitializeFn_;
- contextLostFn = contextLostFn_;
- context = context_;
+ host = std::move(host_);
}
bool CustomLayer::Impl::hasLayoutDifference(const Layer::Impl&) const {
diff --git a/src/mbgl/style/layers/custom_layer_impl.hpp b/src/mbgl/style/layers/custom_layer_impl.hpp
index 62efbbe15b..a41962c276 100644
--- a/src/mbgl/style/layers/custom_layer_impl.hpp
+++ b/src/mbgl/style/layers/custom_layer_impl.hpp
@@ -3,6 +3,8 @@
#include <mbgl/style/layer_impl.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
+#include <memory>
+
namespace mbgl {
class TransformState;
@@ -12,20 +14,12 @@ namespace style {
class CustomLayer::Impl : public Layer::Impl {
public:
Impl(const std::string& id,
- CustomLayerInitializeFunction,
- CustomLayerRenderFunction,
- CustomLayerContextLostFunction,
- CustomLayerDeinitializeFunction,
- void* context);
+ std::unique_ptr<CustomLayerHost> host);
bool hasLayoutDifference(const Layer::Impl&) const override;
void stringifyLayout(rapidjson::Writer<rapidjson::StringBuffer>&) const override;
- CustomLayerInitializeFunction initializeFn = nullptr;
- CustomLayerRenderFunction renderFn = nullptr;
- CustomLayerContextLostFunction contextLostFn = nullptr;
- CustomLayerDeinitializeFunction deinitializeFn = nullptr;
- void* context = nullptr;
+ std::shared_ptr<CustomLayerHost> host;
};
} // namespace style
diff --git a/src/mbgl/style/layers/fill_extrusion_layer.cpp b/src/mbgl/style/layers/fill_extrusion_layer.cpp
index 62f92cef75..c5b4ef0ef3 100644
--- a/src/mbgl/style/layers/fill_extrusion_layer.cpp
+++ b/src/mbgl/style/layers/fill_extrusion_layer.cpp
@@ -81,12 +81,14 @@ void FillExtrusionLayer::setMinZoom(float minZoom) {
auto impl_ = mutableImpl();
impl_->minZoom = minZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
void FillExtrusionLayer::setMaxZoom(float maxZoom) {
auto impl_ = mutableImpl();
impl_->maxZoom = maxZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
// Layout properties
diff --git a/src/mbgl/style/layers/fill_layer.cpp b/src/mbgl/style/layers/fill_layer.cpp
index 65975752db..99a2a51ed0 100644
--- a/src/mbgl/style/layers/fill_layer.cpp
+++ b/src/mbgl/style/layers/fill_layer.cpp
@@ -81,12 +81,14 @@ void FillLayer::setMinZoom(float minZoom) {
auto impl_ = mutableImpl();
impl_->minZoom = minZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
void FillLayer::setMaxZoom(float maxZoom) {
auto impl_ = mutableImpl();
impl_->maxZoom = maxZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
// Layout properties
diff --git a/src/mbgl/style/layers/heatmap_layer.cpp b/src/mbgl/style/layers/heatmap_layer.cpp
index 4989ff15f1..3f7881ddd3 100644
--- a/src/mbgl/style/layers/heatmap_layer.cpp
+++ b/src/mbgl/style/layers/heatmap_layer.cpp
@@ -85,12 +85,14 @@ void HeatmapLayer::setMinZoom(float minZoom) {
auto impl_ = mutableImpl();
impl_->minZoom = minZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
void HeatmapLayer::setMaxZoom(float maxZoom) {
auto impl_ = mutableImpl();
impl_->maxZoom = maxZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
// Layout properties
diff --git a/src/mbgl/style/layers/hillshade_layer.cpp b/src/mbgl/style/layers/hillshade_layer.cpp
index ea736af1ad..e352ae090c 100644
--- a/src/mbgl/style/layers/hillshade_layer.cpp
+++ b/src/mbgl/style/layers/hillshade_layer.cpp
@@ -59,12 +59,14 @@ void HillshadeLayer::setMinZoom(float minZoom) {
auto impl_ = mutableImpl();
impl_->minZoom = minZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
void HillshadeLayer::setMaxZoom(float maxZoom) {
auto impl_ = mutableImpl();
impl_->maxZoom = maxZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
// Layout properties
diff --git a/src/mbgl/style/layers/layer.cpp.ejs b/src/mbgl/style/layers/layer.cpp.ejs
index 657a7f5a8a..6d748311bf 100644
--- a/src/mbgl/style/layers/layer.cpp.ejs
+++ b/src/mbgl/style/layers/layer.cpp.ejs
@@ -108,12 +108,14 @@ void <%- camelize(type) %>Layer::setMinZoom(float minZoom) {
auto impl_ = mutableImpl();
impl_->minZoom = minZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
void <%- camelize(type) %>Layer::setMaxZoom(float maxZoom) {
auto impl_ = mutableImpl();
impl_->maxZoom = maxZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
// Layout properties
diff --git a/src/mbgl/style/layers/line_layer.cpp b/src/mbgl/style/layers/line_layer.cpp
index 1c7f0d28ee..56eac34c00 100644
--- a/src/mbgl/style/layers/line_layer.cpp
+++ b/src/mbgl/style/layers/line_layer.cpp
@@ -82,12 +82,14 @@ void LineLayer::setMinZoom(float minZoom) {
auto impl_ = mutableImpl();
impl_->minZoom = minZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
void LineLayer::setMaxZoom(float maxZoom) {
auto impl_ = mutableImpl();
impl_->maxZoom = maxZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
// Layout properties
diff --git a/src/mbgl/style/layers/raster_layer.cpp b/src/mbgl/style/layers/raster_layer.cpp
index a9a8d273fa..36b2e3e027 100644
--- a/src/mbgl/style/layers/raster_layer.cpp
+++ b/src/mbgl/style/layers/raster_layer.cpp
@@ -59,12 +59,14 @@ void RasterLayer::setMinZoom(float minZoom) {
auto impl_ = mutableImpl();
impl_->minZoom = minZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
void RasterLayer::setMaxZoom(float maxZoom) {
auto impl_ = mutableImpl();
impl_->maxZoom = maxZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
// Layout properties
diff --git a/src/mbgl/style/layers/symbol_layer.cpp b/src/mbgl/style/layers/symbol_layer.cpp
index d1a1ba246e..c940f3b00a 100644
--- a/src/mbgl/style/layers/symbol_layer.cpp
+++ b/src/mbgl/style/layers/symbol_layer.cpp
@@ -82,12 +82,14 @@ void SymbolLayer::setMinZoom(float minZoom) {
auto impl_ = mutableImpl();
impl_->minZoom = minZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
void SymbolLayer::setMaxZoom(float maxZoom) {
auto impl_ = mutableImpl();
impl_->maxZoom = maxZoom;
baseImpl = std::move(impl_);
+ observer->onLayerChanged(*this);
}
// Layout properties
diff --git a/src/mbgl/tile/geometry_tile.cpp b/src/mbgl/tile/geometry_tile.cpp
index 82d0c91806..a99cb91d26 100644
--- a/src/mbgl/tile/geometry_tile.cpp
+++ b/src/mbgl/tile/geometry_tile.cpp
@@ -125,23 +125,16 @@ void GeometryTile::setShowCollisionBoxes(const bool showCollisionBoxes_) {
}
void GeometryTile::onLayout(LayoutResult result, const uint64_t resultCorrelationID) {
- // Don't mark ourselves loaded or renderable until the first successful placement
- // TODO: Ideally we'd render this tile without symbols as long as this tile wasn't
- // replacing a tile at a different zoom that _did_ have symbols.
- (void)resultCorrelationID;
- nonSymbolBuckets = std::move(result.nonSymbolBuckets);
- pendingFeatureIndex = std::move(result.featureIndex);
- pendingData = std::move(result.tileData);
- observer->onTileChanged(*this);
-}
-
-void GeometryTile::onPlacement(PlacementResult result, const uint64_t resultCorrelationID) {
loaded = true;
renderable = true;
if (resultCorrelationID == correlationID) {
pending = false;
}
- symbolBuckets = std::move(result.symbolBuckets);
+
+ buckets = std::move(result.buckets);
+
+ featureIndexPendingCommit = { std::move(result.featureIndex) };
+
if (result.glyphAtlasImage) {
glyphAtlasImage = std::move(*result.glyphAtlasImage);
}
@@ -183,11 +176,7 @@ void GeometryTile::upload(gl::Context& context) {
}
};
- for (auto& entry : nonSymbolBuckets) {
- uploadFn(*entry.second);
- }
-
- for (auto& entry : symbolBuckets) {
+ for (auto& entry : buckets) {
uploadFn(*entry.second);
}
@@ -203,7 +192,6 @@ void GeometryTile::upload(gl::Context& context) {
}
Bucket* GeometryTile::getBucket(const Layer::Impl& layer) const {
- const auto& buckets = layer.type == LayerType::Symbol ? symbolBuckets : nonSymbolBuckets;
const auto it = buckets.find(layer.id);
if (it == buckets.end()) {
return nullptr;
@@ -214,11 +202,11 @@ Bucket* GeometryTile::getBucket(const Layer::Impl& layer) const {
}
void GeometryTile::commitFeatureIndex() {
- if (pendingFeatureIndex) {
- featureIndex = std::move(pendingFeatureIndex);
- }
- if (pendingData) {
- data = std::move(pendingData);
+ // We commit our pending FeatureIndex when a global placement has run,
+ // synchronizing the global CollisionIndex with the latest buckets/FeatureIndex
+ if (featureIndexPendingCommit) {
+ featureIndex = std::move(*featureIndexPendingCommit);
+ featureIndexPendingCommit = nullopt;
}
}
@@ -230,7 +218,7 @@ void GeometryTile::queryRenderedFeatures(
const RenderedQueryOptions& options,
const CollisionIndex& collisionIndex) {
- if (!featureIndex || !data) return;
+ if (!getData()) return;
// Determine the additional radius needed factoring in property functions
float additionalRadius = 0;
@@ -247,7 +235,6 @@ void GeometryTile::queryRenderedFeatures(
util::tileSize * id.overscaleFactor(),
std::pow(2, transformState.getZoom() - id.overscaledZ),
options,
- *data,
id.toUnwrapped(),
sourceID,
layers,
@@ -259,8 +246,8 @@ void GeometryTile::querySourceFeatures(
std::vector<Feature>& result,
const SourceQueryOptions& options) {
- // Data not yet available
- if (!data) {
+ // Data not yet available, or tile is empty
+ if (!getData()) {
return;
}
@@ -273,7 +260,7 @@ void GeometryTile::querySourceFeatures(
for (auto sourceLayer : *options.sourceLayers) {
// Go throught all sourceLayers, if any
// to gather all the features
- auto layer = data->getLayer(sourceLayer);
+ auto layer = getData()->getLayer(sourceLayer);
if (layer) {
auto featureCount = layer->featureCount();
diff --git a/src/mbgl/tile/geometry_tile.hpp b/src/mbgl/tile/geometry_tile.hpp
index 00a4aafadf..418db4a0b2 100644
--- a/src/mbgl/tile/geometry_tile.hpp
+++ b/src/mbgl/tile/geometry_tile.hpp
@@ -65,33 +65,21 @@ public:
class LayoutResult {
public:
- std::unordered_map<std::string, std::shared_ptr<Bucket>> nonSymbolBuckets;
+ std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets;
std::unique_ptr<FeatureIndex> featureIndex;
- std::unique_ptr<GeometryTileData> tileData;
-
- LayoutResult(std::unordered_map<std::string, std::shared_ptr<Bucket>> nonSymbolBuckets_,
- std::unique_ptr<FeatureIndex> featureIndex_,
- std::unique_ptr<GeometryTileData> tileData_)
- : nonSymbolBuckets(std::move(nonSymbolBuckets_)),
- featureIndex(std::move(featureIndex_)),
- tileData(std::move(tileData_)) {}
- };
- void onLayout(LayoutResult, uint64_t correlationID);
-
- class PlacementResult {
- public:
- std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets;
optional<AlphaImage> glyphAtlasImage;
optional<PremultipliedImage> iconAtlasImage;
- PlacementResult(std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets_,
- optional<AlphaImage> glyphAtlasImage_,
- optional<PremultipliedImage> iconAtlasImage_)
- : symbolBuckets(std::move(symbolBuckets_)),
+ LayoutResult(std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets_,
+ std::unique_ptr<FeatureIndex> featureIndex_,
+ optional<AlphaImage> glyphAtlasImage_,
+ optional<PremultipliedImage> iconAtlasImage_)
+ : buckets(std::move(buckets_)),
+ featureIndex(std::move(featureIndex_)),
glyphAtlasImage(std::move(glyphAtlasImage_)),
iconAtlasImage(std::move(iconAtlasImage_)) {}
};
- void onPlacement(PlacementResult, uint64_t correlationID);
+ void onLayout(LayoutResult, uint64_t correlationID);
void onError(std::exception_ptr, uint64_t correlationID);
@@ -104,7 +92,7 @@ public:
protected:
const GeometryTileData* getData() {
- return data.get();
+ return featureIndex ? featureIndex->getData() : nullptr;
}
private:
@@ -123,17 +111,14 @@ private:
uint64_t correlationID = 0;
- std::unordered_map<std::string, std::shared_ptr<Bucket>> nonSymbolBuckets;
+ std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets;
+
+ optional<std::unique_ptr<FeatureIndex>> featureIndexPendingCommit;
std::unique_ptr<FeatureIndex> featureIndex;
- std::unique_ptr<FeatureIndex> pendingFeatureIndex;
- std::unique_ptr<const GeometryTileData> data;
- std::unique_ptr<const GeometryTileData> pendingData;
optional<AlphaImage> glyphAtlasImage;
optional<PremultipliedImage> iconAtlasImage;
- std::unordered_map<std::string, std::shared_ptr<Bucket>> symbolBuckets;
-
const MapMode mode;
bool showCollisionBoxes;
diff --git a/src/mbgl/tile/geometry_tile_worker.cpp b/src/mbgl/tile/geometry_tile_worker.cpp
index 8b6f1f63bf..1378ad5d3a 100644
--- a/src/mbgl/tile/geometry_tile_worker.cpp
+++ b/src/mbgl/tile/geometry_tile_worker.cpp
@@ -41,48 +41,73 @@ GeometryTileWorker::GeometryTileWorker(ActorRef<GeometryTileWorker> self_,
GeometryTileWorker::~GeometryTileWorker() = default;
/*
- NOTE: The comments below are technically correct, but currently
- conceptually misleading. The change to foreground label placement
- means that:
- (1) "placement" here is a misnomer: the remaining role of
- "attemptPlacement" is symbol buffer generation
- (2) Once a tile has completed layout, we will only run
- "attemptPlacement" once
- (3) Tiles won't be rendered until "attemptPlacement" has run once
-
- TODO: Simplify GeometryTileWorker to fit its new role
- https://github.com/mapbox/mapbox-gl-native/issues/10457
-
GeometryTileWorker is a state machine. This is its transition diagram.
States are indicated by [state], lines are transitions triggered by
messages, (parentheses) are actions taken on transition.
- [idle] <----------------------------.
- | |
- set{Data,Layers,Placement}, symbolDependenciesChanged |
- | |
- (do layout/placement; self-send "coalesced") |
- v |
- [coalescing] --- coalesced ------------.
- | |
- .-----------------. .---------------.
+ [Idle] <-------------------------.
+ | |
+ set{Data,Layers}, symbolDependenciesChanged, |
+ setShowCollisionBoxes |
+ | |
+ (do parse and/or symbol layout; self-send "coalesced") |
+ v |
+ [Coalescing] --- coalesced ---------.
+ | |
+ .-----------. .---------------------.
| |
- .--- set{Data,Layers} setPlacement -----.
- | | | |
- | v v |
- .-- [need layout] <-- set{Data,Layers} -- [need placement] --.
+ .--- set{Data,Layers} setShowCollisionBoxes,
+ | | symbolDependenciesChanged --.
+ | | | |
+ | v v |
+ .-- [NeedsParse] <-- set{Data,Layers} -- [NeedsSymbolLayout] ---.
| |
coalesced coalesced
| |
v v
- (do layout or placement; self-send "coalesced"; goto [coalescing])
-
- The idea is that in the [idle] state, layout or placement happens immediately
- in response to a "set" message. During this processing, multiple "set" messages
- might get queued in the mailbox. At the end of processing, we self-send "coalesced",
- read all the queued messages until we get to "coalesced", and then redo either
- layout or placement if there were one or more "set"s (with layout taking priority,
- since it will trigger placement when complete), or return to the [idle] state if not.
+ (do parse or symbol layout; self-send "coalesced"; goto [coalescing])
+
+ The idea is that in the [idle] state, parsing happens immediately in response to
+ a "set" message, and symbol layout happens once all symbol dependencies are met.
+ During this processing, multiple "set" messages might get queued in the mailbox.
+ At the end of processing, we self-send "coalesced", read all the queued messages
+ until we get to "coalesced", and then re-parse if there were one or more "set"s or
+ return to the [idle] state if not.
+
+ One important goal of the design is to prevent starvation. Under heavy load new
+ requests for tiles should not prevent in progress request from completing.
+ It is nevertheless possible to restart an in-progress request:
+
+ - [Idle] setData -> parse()
+ sends getGlyphs, hasPendingSymbolDependencies() is true
+ enters [Coalescing], sends coalesced
+ - [Coalescing] coalesced -> [Idle]
+ - [Idle] setData -> new parse(), interrupts old parse()
+ sends getGlyphs, hasPendingSymbolDependencies() is true
+ enters [Coalescing], sends coalesced
+ - [Coalescing] onGlyphsAvailable -> [NeedsSymbolLayout]
+ hasPendingSymbolDependencies() may or may not be true
+ - [NeedsSymbolLayout] coalesced -> performSymbolLayout()
+ Generates result depending on whether dependencies are met
+ -> [Idle]
+
+ In this situation, we are counting on the idea that even with rapid changes to
+ the tile's data, the set of glyphs/images it requires will not keep growing without
+ limit.
+
+ Although parsing (which populates all non-symbol buckets and requests dependencies
+ for symbol buckets) is internally separate from symbol layout, we only return
+ results to the foreground when we have completed both steps. Because we _move_
+ the result buckets to the foreground, it is necessary to re-generate all buckets from
+ scratch for `setShowCollisionBoxes`, even though it only affects symbol layers.
+
+ The GL JS equivalent (in worker_tile.js and vector_tile_worker_source.js)
+ is somewhat simpler because it relies on getGlyphs/getImages calls that transfer
+ an entire set of glyphs/images on every tile load, while the native logic
+ maintains a local state that can be incrementally updated. Because each tile load
+ call becomes self-contained, the equivalent of the coalescing logic is handled by
+ 'reloadTile' queueing a single extra 'reloadTile' callback to run after the next
+ completed parse.
*/
void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_, uint64_t correlationID_) {
@@ -92,14 +117,14 @@ void GeometryTileWorker::setData(std::unique_ptr<const GeometryTileData> data_,
switch (state) {
case Idle:
- redoLayout();
+ parse();
coalesce();
break;
case Coalescing:
- case NeedLayout:
- case NeedPlacement:
- state = NeedLayout;
+ case NeedsParse:
+ case NeedsSymbolLayout:
+ state = NeedsParse;
break;
}
} catch (...) {
@@ -114,16 +139,16 @@ void GeometryTileWorker::setLayers(std::vector<Immutable<Layer::Impl>> layers_,
switch (state) {
case Idle:
- redoLayout();
+ parse();
coalesce();
break;
case Coalescing:
- case NeedPlacement:
- state = NeedLayout;
+ case NeedsSymbolLayout:
+ state = NeedsParse;
break;
- case NeedLayout:
+ case NeedsParse:
break;
}
} catch (...) {
@@ -138,16 +163,20 @@ void GeometryTileWorker::setShowCollisionBoxes(bool showCollisionBoxes_, uint64_
switch (state) {
case Idle:
- attemptPlacement();
- coalesce();
+ if (!hasPendingParseResult()) {
+ // Trigger parse if nothing is in flight, otherwise symbol layout will automatically
+ // pick up the change
+ parse();
+ coalesce();
+ }
break;
case Coalescing:
- state = NeedPlacement;
+ state = NeedsSymbolLayout;
break;
- case NeedPlacement:
- case NeedLayout:
+ case NeedsSymbolLayout:
+ case NeedsParse:
break;
}
} catch (...) {
@@ -160,19 +189,23 @@ void GeometryTileWorker::symbolDependenciesChanged() {
switch (state) {
case Idle:
if (symbolLayoutsNeedPreparation) {
- attemptPlacement();
+ // symbolLayoutsNeedPreparation can only be set true by parsing
+ // and the parse result can only be cleared by performSymbolLayout
+ // which also clears symbolLayoutsNeedPreparation
+ assert(hasPendingParseResult());
+ performSymbolLayout();
coalesce();
}
break;
case Coalescing:
if (symbolLayoutsNeedPreparation) {
- state = NeedPlacement;
+ state = NeedsSymbolLayout;
}
break;
- case NeedPlacement:
- case NeedLayout:
+ case NeedsSymbolLayout:
+ case NeedsParse:
break;
}
} catch (...) {
@@ -191,13 +224,16 @@ void GeometryTileWorker::coalesced() {
state = Idle;
break;
- case NeedLayout:
- redoLayout();
+ case NeedsParse:
+ parse();
coalesce();
break;
- case NeedPlacement:
- attemptPlacement();
+ case NeedsSymbolLayout:
+ // We may have entered NeedsSymbolLayout while coalescing
+ // after a performSymbolLayout. In that case, we need to
+ // start over with parsing in order to do another layout.
+ hasPendingParseResult() ? performSymbolLayout() : parse();
coalesce();
break;
}
@@ -279,7 +315,7 @@ static std::vector<std::unique_ptr<RenderLayer>> toRenderLayers(const std::vecto
return renderLayers;
}
-void GeometryTileWorker::redoLayout() {
+void GeometryTileWorker::parse() {
if (!data || !layers) {
return;
}
@@ -292,8 +328,8 @@ void GeometryTileWorker::redoLayout() {
}
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>();
+ buckets.clear();
+ featureIndex = std::make_unique<FeatureIndex>(*data ? (*data)->clone() : nullptr);
BucketParameters parameters { id, mode, pixelRatio };
GlyphDependencies glyphDependencies;
@@ -368,13 +404,7 @@ void GeometryTileWorker::redoLayout() {
requestNewGlyphs(glyphDependencies);
requestNewImages(imageDependencies);
- parent.invoke(&GeometryTile::onLayout, GeometryTile::LayoutResult {
- std::move(buckets),
- std::move(featureIndex),
- *data ? (*data)->clone() : nullptr,
- }, correlationID);
-
- attemptPlacement();
+ performSymbolLayout();
}
bool GeometryTileWorker::hasPendingSymbolDependencies() const {
@@ -385,9 +415,13 @@ bool GeometryTileWorker::hasPendingSymbolDependencies() const {
}
return !pendingImageDependencies.empty();
}
+
+bool GeometryTileWorker::hasPendingParseResult() const {
+ return bool(featureIndex);
+}
-void GeometryTileWorker::attemptPlacement() {
- if (!data || !layers || hasPendingSymbolDependencies()) {
+void GeometryTileWorker::performSymbolLayout() {
+ if (!data || !layers || !hasPendingParseResult() || hasPendingSymbolDependencies()) {
return;
}
@@ -414,8 +448,6 @@ void GeometryTileWorker::attemptPlacement() {
symbolLayoutsNeedPreparation = false;
}
- std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets;
-
for (auto& symbolLayout : symbolLayouts) {
if (obsolete) {
return;
@@ -435,11 +467,12 @@ void GeometryTileWorker::attemptPlacement() {
}
firstLoad = false;
-
- parent.invoke(&GeometryTile::onPlacement, GeometryTile::PlacementResult {
+
+ parent.invoke(&GeometryTile::onLayout, GeometryTile::LayoutResult {
std::move(buckets),
+ std::move(featureIndex),
std::move(glyphAtlasImage),
- std::move(iconAtlasImage),
+ std::move(iconAtlasImage)
}, correlationID);
}
diff --git a/src/mbgl/tile/geometry_tile_worker.hpp b/src/mbgl/tile/geometry_tile_worker.hpp
index 0276392679..b5417c8114 100644
--- a/src/mbgl/tile/geometry_tile_worker.hpp
+++ b/src/mbgl/tile/geometry_tile_worker.hpp
@@ -8,6 +8,8 @@
#include <mbgl/util/optional.hpp>
#include <mbgl/util/immutable.hpp>
#include <mbgl/style/layer_impl.hpp>
+#include <mbgl/geometry/feature_index.hpp>
+#include <mbgl/renderer/bucket.hpp>
#include <atomic>
#include <memory>
@@ -43,8 +45,8 @@ public:
private:
void coalesced();
- void redoLayout();
- void attemptPlacement();
+ void parse();
+ void performSymbolLayout();
void coalesce();
@@ -53,6 +55,7 @@ private:
void symbolDependenciesChanged();
bool hasPendingSymbolDependencies() const;
+ bool hasPendingParseResult() const;
ActorRef<GeometryTileWorker> self;
ActorRef<GeometryTile> parent;
@@ -62,12 +65,15 @@ private:
const std::atomic<bool>& obsolete;
const MapMode mode;
const float pixelRatio;
+
+ std::unique_ptr<FeatureIndex> featureIndex;
+ std::unordered_map<std::string, std::shared_ptr<Bucket>> buckets;
enum State {
Idle,
Coalescing,
- NeedLayout,
- NeedPlacement
+ NeedsParse,
+ NeedsSymbolLayout
};
State state = Idle;
diff --git a/src/mbgl/util/color.cpp b/src/mbgl/util/color.cpp
index c8145d36e7..55f1b65436 100644
--- a/src/mbgl/util/color.cpp
+++ b/src/mbgl/util/color.cpp
@@ -23,11 +23,25 @@ optional<Color> Color::parse(const std::string& s) {
}
std::string Color::stringify() const {
+ std::array<double, 4> array = toArray();
return "rgba(" +
- util::toString(r * 255 / a) + "," +
- util::toString(g * 255 / a) + "," +
- util::toString(b * 255 / a) + "," +
- util::toString(a) + ")";
+ util::toString(array[0]) + "," +
+ util::toString(array[1]) + "," +
+ util::toString(array[2]) + "," +
+ util::toString(array[3]) + ")";
+}
+
+std::array<double, 4> Color::toArray() const {
+ if (a == 0) {
+ return {{ 0, 0, 0, 0 }};
+ } else {
+ return {{
+ r * 255 / a,
+ g * 255 / a,
+ b * 255 / a,
+ a,
+ }};
+ }
}
} // namespace mbgl
diff --git a/test/api/custom_layer.test.cpp b/test/api/custom_layer.test.cpp
index eb1d7e0d3a..6cb148a349 100644
--- a/test/api/custom_layer.test.cpp
+++ b/test/api/custom_layer.test.cpp
@@ -34,19 +34,8 @@ void main() {
// layer implementation because it is intended to reflect how someone using custom layers
// might actually write their own implementation.
-class TestLayer {
+class TestLayer : public mbgl::style::CustomLayerHost {
public:
- ~TestLayer() {
- if (program) {
- MBGL_CHECK_ERROR(glDeleteBuffers(1, &buffer));
- MBGL_CHECK_ERROR(glDetachShader(program, vertexShader));
- MBGL_CHECK_ERROR(glDetachShader(program, fragmentShader));
- MBGL_CHECK_ERROR(glDeleteShader(vertexShader));
- MBGL_CHECK_ERROR(glDeleteShader(fragmentShader));
- MBGL_CHECK_ERROR(glDeleteProgram(program));
- }
- }
-
void initialize() {
program = MBGL_CHECK_ERROR(glCreateProgram());
vertexShader = MBGL_CHECK_ERROR(glCreateShader(GL_VERTEX_SHADER));
@@ -67,7 +56,7 @@ public:
MBGL_CHECK_ERROR(glBufferData(GL_ARRAY_BUFFER, 6 * sizeof(GLfloat), triangle, GL_STATIC_DRAW));
}
- void render() {
+ void render(const mbgl::style::CustomLayerRenderParameters&) {
MBGL_CHECK_ERROR(glUseProgram(program));
MBGL_CHECK_ERROR(glBindBuffer(GL_ARRAY_BUFFER, buffer));
MBGL_CHECK_ERROR(glEnableVertexAttribArray(a_pos));
@@ -75,6 +64,19 @@ public:
MBGL_CHECK_ERROR(glDrawArrays(GL_TRIANGLE_STRIP, 0, 3));
}
+ void contextLost() {}
+
+ void deinitialize() {
+ if (program) {
+ MBGL_CHECK_ERROR(glDeleteBuffers(1, &buffer));
+ MBGL_CHECK_ERROR(glDetachShader(program, vertexShader));
+ MBGL_CHECK_ERROR(glDetachShader(program, fragmentShader));
+ MBGL_CHECK_ERROR(glDeleteShader(vertexShader));
+ MBGL_CHECK_ERROR(glDeleteShader(fragmentShader));
+ MBGL_CHECK_ERROR(glDeleteProgram(program));
+ }
+ }
+
GLuint program = 0;
GLuint vertexShader = 0;
GLuint fragmentShader = 0;
@@ -95,15 +97,7 @@ TEST(CustomLayer, Basic) {
map.setLatLngZoom({ 37.8, -122.5 }, 10);
map.getStyle().addLayer(std::make_unique<CustomLayer>(
"custom",
- [] (void* context) {
- reinterpret_cast<TestLayer*>(context)->initialize();
- },
- [] (void* context, const CustomLayerRenderParameters&) {
- reinterpret_cast<TestLayer*>(context)->render();
- },
- [] (void* context) {
- delete reinterpret_cast<TestLayer*>(context);
- }, new TestLayer()));
+ std::make_unique<TestLayer>()));
auto layer = std::make_unique<FillLayer>("landcover", "mapbox");
layer->setSourceLayer("landcover");
diff --git a/test/style/conversion/stringify.test.cpp b/test/style/conversion/stringify.test.cpp
index 0b2940a0e0..136f276aaf 100644
--- a/test/style/conversion/stringify.test.cpp
+++ b/test/style/conversion/stringify.test.cpp
@@ -80,23 +80,25 @@ TEST(Stringify, Filter) {
}
TEST(Stringify, CameraFunction) {
+ ASSERT_EQ(stringify(CameraFunction<float>(ExponentialStops<float> { {{0, 1}}, 1 })),
+ "[\"interpolate\",[\"linear\"],[\"zoom\"],0.0,1.0]");
ASSERT_EQ(stringify(CameraFunction<float>(ExponentialStops<float> { {{0, 1}}, 2 })),
- "{\"type\":\"exponential\",\"base\":2.0,\"stops\":[[0.0,1.0]]}");
+ "[\"interpolate\",[\"exponential\",2.0],[\"zoom\"],0.0,1.0]");
ASSERT_EQ(stringify(CameraFunction<float>(IntervalStops<float> { {{0, 1}} })),
- "{\"type\":\"interval\",\"stops\":[[0.0,1.0]]}");
+ "[\"step\",[\"zoom\"],0.0,1.0]");
}
TEST(Stringify, SourceFunction) {
ASSERT_EQ(stringify(SourceFunction<float>("property", ExponentialStops<float> { {{0, 1}}, 2 })),
- "{\"property\":\"property\",\"type\":\"exponential\",\"base\":2.0,\"stops\":[[0.0,1.0]]}");
+ "[\"interpolate\",[\"exponential\",2.0],[\"number\",[\"get\",\"property\"]],0.0,1.0]");
ASSERT_EQ(stringify(SourceFunction<float>("property", IntervalStops<float> { {{0, 1}} })),
- "{\"property\":\"property\",\"type\":\"interval\",\"stops\":[[0.0,1.0]]}");
+ "[\"step\",[\"number\",[\"get\",\"property\"]],0.0,1.0]");
ASSERT_EQ(stringify(SourceFunction<float>("property", CategoricalStops<float> { {{CategoricalValue(true), 1}} })),
- "{\"property\":\"property\",\"type\":\"categorical\",\"stops\":[[true,1.0]]}");
+ "[\"case\",[\"boolean\",[\"get\",\"property\"]],1.0,[\"error\"]]");
ASSERT_EQ(stringify(SourceFunction<float>("property", IdentityStops<float> {})),
- "{\"property\":\"property\",\"type\":\"identity\"}");
+ "[\"number\",[\"get\",\"property\"]]");
ASSERT_EQ(stringify(SourceFunction<float>("property", IdentityStops<float> {}, 0.0f)),
- "{\"property\":\"property\",\"type\":\"identity\",\"default\":0.0}");
+ "[\"number\",[\"get\",\"property\"]]");
}
TEST(Stringify, CompositeFunction) {
@@ -108,16 +110,17 @@ TEST(Stringify, CompositeFunction) {
},
2
}, 0.0f)),
- "{\"property\":\"property\",\"type\":\"exponential\",\"base\":2.0,"
- "\"stops\":["
- "[{\"zoom\":0.0,\"value\":0.0},1.0],"
- "[{\"zoom\":1.0,\"value\":0.0},1.0]],\"default\":0.0}");
+ "[\"interpolate\","
+ "[\"linear\"],"
+ "[\"zoom\"],"
+ "0.0,[\"interpolate\",[\"exponential\",2.0],[\"number\",[\"get\",\"property\"]],0.0,1.0],"
+ "1.0,[\"interpolate\",[\"exponential\",2.0],[\"number\",[\"get\",\"property\"]],0.0,1.0]]");
}
TEST(Stringify, PropertyValue) {
ASSERT_EQ(stringify(PropertyValue<float>(1)), "1.0");
ASSERT_EQ(stringify(PropertyValue<float>(CameraFunction<float>(ExponentialStops<float> { {{0, 1}}, 2 }))),
- "{\"type\":\"exponential\",\"base\":2.0,\"stops\":[[0.0,1.0]]}");
+ "[\"interpolate\",[\"exponential\",2.0],[\"zoom\"],0.0,1.0]");
}
TEST(Stringify, Layout) {
diff --git a/test/style/expression/expression.test.cpp b/test/style/expression/expression.test.cpp
index 694569695c..fe5c261be1 100644
--- a/test/style/expression/expression.test.cpp
+++ b/test/style/expression/expression.test.cpp
@@ -49,7 +49,7 @@ TEST_P(ExpressionEqualityTest, ExpressionEquality) {
assert(!document.HasParseError());
const JSValue* expression = &document;
expression::ParsingContext ctx;
- expression::ParseResult parsed = ctx.parse(conversion::Convertible(expression));
+ expression::ParseResult parsed = ctx.parseExpression(conversion::Convertible(expression));
if (!parsed) {
error_ = ctx.getErrors().size() > 0 ? ctx.getErrors()[0].message : "failed to parse";
};
diff --git a/test/style/filter.test.cpp b/test/style/filter.test.cpp
index 6f261c43ec..49edcaef45 100644
--- a/test/style/filter.test.cpp
+++ b/test/style/filter.test.cpp
@@ -11,14 +11,19 @@
using namespace mbgl;
using namespace mbgl::style;
-bool filter(const char * json, const PropertyMap& featureProperties = {{}}, optional<FeatureIdentifier> featureId = {}, FeatureType featureType = FeatureType::Point, GeometryCollection featureGeometry = {}) {
+bool filter(const char * json,
+ const PropertyMap& featureProperties = {{}},
+ optional<FeatureIdentifier> featureId = {},
+ FeatureType featureType = FeatureType::Point,
+ GeometryCollection featureGeometry = {},
+ float zoom = 0.0f) {
conversion::Error error;
optional<Filter> filter = conversion::convertJSON<Filter>(json, error);
EXPECT_TRUE(bool(filter));
EXPECT_EQ(error.message, "");
StubGeometryTileFeature feature { featureId, featureType, featureGeometry, featureProperties };
- expression::EvaluationContext context = { &feature };
+ expression::EvaluationContext context = { zoom, &feature };
return (*filter)(context);
}
@@ -109,3 +114,8 @@ TEST(Filter, PropertyExpression) {
ASSERT_TRUE(filter("[\"==\", [\"get\", \"two\"], 2]", {{"two", int64_t(2)}}));
ASSERT_FALSE(filter("[\"==\", [\"get\", \"two\"], 4]", {{"two", int64_t(2)}}));
}
+
+TEST(Filter, ZoomExpressionNested) {
+ ASSERT_TRUE(filter(R"(["==", ["get", "two"], ["zoom"]])", {{"two", int64_t(2)}}, {}, FeatureType::Point, {}, 2.0f));
+ ASSERT_FALSE(filter(R"(["==", ["get", "two"], ["+", ["zoom"], 1]])", {{"two", int64_t(2)}}, {}, FeatureType::Point, {}, 2.0f));
+}
diff --git a/test/tile/vector_tile.test.cpp b/test/tile/vector_tile.test.cpp
index 9d42f7ae74..cd53c7c4a4 100644
--- a/test/tile/vector_tile.test.cpp
+++ b/test/tile/vector_tile.test.cpp
@@ -65,39 +65,6 @@ TEST(VectorTile, onError) {
EXPECT_TRUE(tile.isComplete());
}
-TEST(VectorTile, Issue7615) {
- VectorTileTest test;
- VectorTile tile(OverscaledTileID(0, 0, 0), "source", test.tileParameters, test.tileset);
-
- style::SymbolLayer symbolLayer("symbol", "source");
- std::vector<SymbolInstance> symbolInstances;
- auto symbolBucket = std::make_shared<SymbolBucket>(
- style::SymbolLayoutProperties::PossiblyEvaluated(),
- std::map<
- std::string,
- std::pair<style::IconPaintProperties::PossiblyEvaluated, style::TextPaintProperties::PossiblyEvaluated>>(),
- 16.0f, 1.0f, 0.0f, false, false, false, std::move(symbolInstances));
-
- // Simulate placement of a symbol layer.
- tile.onPlacement(GeometryTile::PlacementResult {
- {{
- symbolLayer.getID(),
- symbolBucket
- }},
- {},
- {},
- }, 0);
-
- // Subsequent onLayout should not cause the existing symbol bucket to be discarded.
- tile.onLayout(GeometryTile::LayoutResult {
- std::unordered_map<std::string, std::shared_ptr<Bucket>>(),
- nullptr,
- nullptr,
- }, 0);
-
- EXPECT_EQ(symbolBucket.get(), tile.getBucket(*symbolLayer.baseImpl));
-}
-
TEST(VectorTile, Issue8542) {
VectorTileTest test;
VectorTile tile(OverscaledTileID(0, 0, 0), "source", test.tileParameters, test.tileset);