summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2016-12-03 15:36:42 -0800
committerMinh Nguyễn <mxn@1ec5.org>2016-12-03 15:36:42 -0800
commit3503c0e7679d5802068fc2ab2420b575a8ae2fc7 (patch)
treed1cfdd3ca2f2fb9761466a61e77d82d8f6b76002
parent84038832e45c2445b43b39ccb2f9e29c8646dac0 (diff)
parent9eb7f88b2c292d322a104c4580c3ef29958b628b (diff)
downloadqtlocation-mapboxgl-3503c0e7679d5802068fc2ab2420b575a8ae2fc7.tar.gz
Merge branch 'release-ios-v3.4.0' into 1ec5-release-ios-v3.4.0-beta.4-master
-rw-r--r--include/mbgl/map/map.hpp2
-rw-r--r--platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java1
-rw-r--r--platform/android/config.cmake6
-rw-r--r--platform/darwin/scripts/generate-style-code.js42
-rw-r--r--platform/darwin/scripts/style-spec-cocoa-conventions-v8.json9
-rw-r--r--platform/darwin/src/MGLBackgroundStyleLayer.h10
-rw-r--r--platform/darwin/src/MGLBackgroundStyleLayer.mm93
-rw-r--r--platform/darwin/src/MGLCircleStyleLayer.h64
-rw-r--r--platform/darwin/src/MGLCircleStyleLayer.mm174
-rw-r--r--platform/darwin/src/MGLFillStyleLayer.h24
-rw-r--r--platform/darwin/src/MGLFillStyleLayer.mm165
-rw-r--r--platform/darwin/src/MGLForegroundStyleLayer.m7
-rw-r--r--platform/darwin/src/MGLGeoJSONSource.mm20
-rw-r--r--platform/darwin/src/MGLGeometry.h7
-rw-r--r--platform/darwin/src/MGLLineStyleLayer.h70
-rw-r--r--platform/darwin/src/MGLLineStyleLayer.mm273
-rw-r--r--platform/darwin/src/MGLMultiPoint.h25
-rw-r--r--platform/darwin/src/MGLMultiPoint.mm108
-rw-r--r--platform/darwin/src/MGLMultiPoint_Private.h2
-rw-r--r--platform/darwin/src/MGLPointCollection.h2
-rw-r--r--platform/darwin/src/MGLPointCollection.mm47
-rw-r--r--platform/darwin/src/MGLPointCollection_Private.h2
-rw-r--r--platform/darwin/src/MGLPolygon.h4
-rw-r--r--platform/darwin/src/MGLPolygon.mm6
-rw-r--r--platform/darwin/src/MGLPolyline.h2
-rw-r--r--platform/darwin/src/MGLPolyline.mm2
-rw-r--r--platform/darwin/src/MGLRasterSource.mm22
-rw-r--r--platform/darwin/src/MGLRasterStyleLayer.h42
-rw-r--r--platform/darwin/src/MGLRasterStyleLayer.mm152
-rw-r--r--platform/darwin/src/MGLRuntimeStylingTests.m.ejs4
-rw-r--r--platform/darwin/src/MGLSource.mm27
-rw-r--r--platform/darwin/src/MGLSource_Private.h9
-rw-r--r--platform/darwin/src/MGLStyle.h185
-rw-r--r--platform/darwin/src/MGLStyle.mm327
-rw-r--r--platform/darwin/src/MGLStyleLayer.mm37
-rw-r--r--platform/darwin/src/MGLStyleLayer.mm.ejs142
-rw-r--r--platform/darwin/src/MGLStyleLayer_Private.h58
-rw-r--r--platform/darwin/src/MGLStyleValue_Private.h100
-rw-r--r--platform/darwin/src/MGLStyle_Private.h5
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.h402
-rw-r--r--platform/darwin/src/MGLSymbolStyleLayer.mm772
-rw-r--r--platform/darwin/src/MGLTileSet.mm6
-rw-r--r--platform/darwin/src/MGLTypes.h13
-rw-r--r--platform/darwin/src/MGLVectorSource.mm22
-rw-r--r--platform/darwin/src/MGLVectorStyleLayer.h7
-rw-r--r--platform/darwin/src/MGLVectorStyleLayer.m9
-rw-r--r--platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm7
-rw-r--r--platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h232
-rw-r--r--platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h.ejs66
-rw-r--r--platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm169
-rw-r--r--platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm.ejs46
-rw-r--r--platform/darwin/test/MGLBackgroundStyleLayerTests.m12
-rw-r--r--platform/darwin/test/MGLCircleStyleLayerTests.m30
-rw-r--r--platform/darwin/test/MGLFillStyleLayerTests.m20
-rw-r--r--platform/darwin/test/MGLFilterTests.mm16
-rw-r--r--platform/darwin/test/MGLLineStyleLayerTests.m52
-rw-r--r--platform/darwin/test/MGLOfflineStorageTests.m1
-rw-r--r--platform/darwin/test/MGLRasterStyleLayerTests.m44
-rw-r--r--platform/darwin/test/MGLStyleLayerTests.h (renamed from platform/darwin/test/MGLMapViewTests.h)2
-rw-r--r--platform/darwin/test/MGLStyleLayerTests.m (renamed from platform/darwin/test/MGLMapViewTests.m)6
-rw-r--r--platform/darwin/test/MGLStyleLayerTests.xib (renamed from platform/darwin/test/MGLMapViewTests.xib)4
-rw-r--r--platform/darwin/test/MGLStyleTests.mm75
-rw-r--r--platform/darwin/test/MGLSymbolStyleLayerTests.m212
-rw-r--r--platform/default/resources/star_tilestream_net.derbin1273 -> 0 bytes
-rw-r--r--platform/ios/CHANGELOG.md28
-rw-r--r--platform/ios/DEVELOPING.md9
-rw-r--r--platform/ios/Mapbox-iOS-SDK-symbols.podspec2
-rw-r--r--platform/ios/Mapbox-iOS-SDK.podspec2
-rw-r--r--platform/ios/app/MBXViewController.m58
-rw-r--r--platform/ios/ios.xcodeproj/project.pbxproj68
-rw-r--r--platform/ios/ios.xcworkspace/contents.xcworkspacedata3
-rw-r--r--platform/ios/resources/api_mapbox_com-digicert.der (renamed from platform/default/resources/api_mapbox_com-digicert.der)bin1913 -> 1913 bytes
-rw-r--r--platform/ios/resources/api_mapbox_com-geotrust.der (renamed from platform/default/resources/api_mapbox_com-geotrust.der)bin1757 -> 1757 bytes
-rw-r--r--platform/ios/resources/api_mapbox_staging.derbin0 -> 1334 bytes
-rw-r--r--platform/ios/src/MGLAPIClient.m2
-rw-r--r--platform/ios/src/MGLMapView.h42
-rw-r--r--platform/ios/src/MGLMapView.mm238
-rw-r--r--platform/ios/src/MGLMapboxEvents.m14
-rw-r--r--platform/ios/src/Mapbox.h1
-rw-r--r--platform/ios/uitest/ios-tests.xcodeproj/project.pbxproj56
-rw-r--r--platform/macos/CHANGELOG.md9
-rw-r--r--platform/macos/DEVELOPING.md9
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/Contents.json6
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/background.imageset/Contents.json15
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/background.imageset/background.pdf69
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/circle.imageset/Contents.json15
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/circle.imageset/circle.pdf70
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/fill.imageset/Contents.json15
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/fill.imageset/fill.pdfbin0 -> 1046 bytes
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/symbol.imageset/Contents.json15
-rw-r--r--platform/macos/app/Assets.xcassets/Layers/symbol.imageset/symbol.pdf71
-rw-r--r--platform/macos/app/Base.lproj/MainMenu.xib38
-rw-r--r--platform/macos/app/Base.lproj/MapDocument.xib188
-rw-r--r--platform/macos/app/MapDocument.h2
-rw-r--r--platform/macos/app/MapDocument.m230
-rw-r--r--platform/macos/app/StyleLayerIconTransformer.h5
-rw-r--r--platform/macos/app/StyleLayerIconTransformer.m38
-rw-r--r--platform/macos/app/resources/background.svg90
-rw-r--r--platform/macos/app/resources/circle.svg67
-rw-r--r--platform/macos/app/resources/fill.svg68
-rw-r--r--platform/macos/app/resources/symbol.svg66
-rw-r--r--platform/macos/macos.xcodeproj/project.pbxproj40
-rw-r--r--platform/macos/src/MGLMapView.h38
-rw-r--r--platform/macos/src/MGLMapView.mm102
-rw-r--r--platform/macos/src/Mapbox.h1
-rw-r--r--src/mbgl/map/map.cpp10
-rw-r--r--src/mbgl/style/style.cpp27
-rw-r--r--src/mbgl/style/style.hpp3
108 files changed, 4870 insertions, 1462 deletions
diff --git a/include/mbgl/map/map.hpp b/include/mbgl/map/map.hpp
index aaec346731..a6e77218b3 100644
--- a/include/mbgl/map/map.hpp
+++ b/include/mbgl/map/map.hpp
@@ -157,11 +157,13 @@ public:
void removeAnnotation(AnnotationID);
// Sources
+ std::vector<style::Source*> getSources();
style::Source* getSource(const std::string& sourceID);
void addSource(std::unique_ptr<style::Source>);
std::unique_ptr<style::Source> removeSource(const std::string& sourceID);
// Layers
+ std::vector<style::Layer*> getLayers();
style::Layer* getLayer(const std::string& layerID);
void addLayer(std::unique_ptr<style::Layer>, const optional<std::string>& beforeLayerID = {});
std::unique_ptr<style::Layer> removeLayer(const std::string& layerID);
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 b7ce27dd6e..7cd36076d3 100644
--- a/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java
+++ b/platform/android/MapboxGLAndroidSDKTestApp/src/androidTest/java/com/mapbox/mapboxsdk/testapp/style/RasterLayerTest.java
@@ -1,6 +1,7 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make android-style-code`.
package com.mapbox.mapboxsdk.testapp.style;
+import android.graphics.Color;
import android.support.test.espresso.Espresso;
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
diff --git a/platform/android/config.cmake b/platform/android/config.cmake
index da0901ed9a..ff02750450 100644
--- a/platform/android/config.cmake
+++ b/platform/android/config.cmake
@@ -33,15 +33,9 @@ macro(mbgl_android_copy_asset source target)
endmacro()
mbgl_android_copy_asset(common/ca-bundle.crt ca-bundle.crt)
-mbgl_android_copy_asset(platform/default/resources/api_mapbox_com-digicert.der api_mapbox_com-digicert.der)
-mbgl_android_copy_asset(platform/default/resources/api_mapbox_com-geotrust.der api_mapbox_com-geotrust.der)
-mbgl_android_copy_asset(platform/default/resources/star_tilestream_net.der star_tilestream_net.der)
add_custom_target(mbgl-copy-android-assets
DEPENDS ${ANDROID_ASSETS_TARGET_DIR}/ca-bundle.crt
- DEPENDS ${ANDROID_ASSETS_TARGET_DIR}/api_mapbox_com-digicert.der
- DEPENDS ${ANDROID_ASSETS_TARGET_DIR}/api_mapbox_com-geotrust.der
- DEPENDS ${ANDROID_ASSETS_TARGET_DIR}/star_tilestream_net.der
)
## mbgl core ##
diff --git a/platform/darwin/scripts/generate-style-code.js b/platform/darwin/scripts/generate-style-code.js
index c4652e4e9b..6b54b5219b 100644
--- a/platform/darwin/scripts/generate-style-code.js
+++ b/platform/darwin/scripts/generate-style-code.js
@@ -4,13 +4,23 @@ const fs = require('fs');
const ejs = require('ejs');
const _ = require('lodash');
const colorParser = require('csscolorparser');
-const spec = _.merge(require('mapbox-gl-style-spec').latest, require('./style-spec-overrides-v8.json'));
require('../../../scripts/style-code');
+const cocoaConventions = require('./style-spec-cocoa-conventions-v8.json');
+let spec = _.merge(require('mapbox-gl-style-spec').latest, require('./style-spec-overrides-v8.json'));
const prefix = 'MGL';
const suffix = 'StyleLayer';
+// Rename properties and keep `original` for use with setters and getters
+_.forOwn(cocoaConventions, function (properties, kind) {
+ _.forOwn(properties, function (newName, oldName) {
+ spec[kind][newName] = spec[kind][oldName];
+ spec[kind][newName].original = oldName;
+ delete spec[kind][oldName];
+ })
+});
+
global.objCName = function (property) {
return camelizeWithLeadingLowercase(property.name);
}
@@ -202,6 +212,10 @@ global.propertyDefault = function (property, layerType) {
return 'an `MGLStyleValue` object containing ' + describeValue(property.default, property, layerType);
};
+global.originalPropertyName = function (property) {
+ return property.original || property.name;
+}
+
global.propertyType = function (property) {
switch (property.type) {
case 'boolean':
@@ -291,6 +305,8 @@ global.mbglType = function(property) {
const layerH = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.h.ejs', 'utf8'), { strict: true });
const layerM = ejs.compile(fs.readFileSync('platform/darwin/src/MGLStyleLayer.mm.ejs', 'utf8'), { strict: true});
const testLayers = ejs.compile(fs.readFileSync('platform/darwin/src/MGLRuntimeStylingTests.m.ejs', 'utf8'), { strict: true});
+const categoryH = ejs.compile(fs.readFileSync('platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h.ejs', 'utf8'), { strict: true});
+const categoryM = ejs.compile(fs.readFileSync('platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm.ejs', 'utf8'), { strict: true});
const layers = Object.keys(spec.layer.type.values).map((type) => {
const layoutProperties = Object.keys(spec[`layout_${type}`]).reduce((memo, name) => {
@@ -309,8 +325,8 @@ const layers = Object.keys(spec.layer.type.values).map((type) => {
return {
type: type,
- layoutProperties: layoutProperties,
- paintProperties: paintProperties,
+ layoutProperties: _.sortBy(layoutProperties, ['name']),
+ paintProperties: _.sortBy(paintProperties, ['name']),
layoutPropertiesByName: spec[`layout_${type}`],
paintPropertiesByName: spec[`paint_${type}`],
};
@@ -335,8 +351,28 @@ ${macosComment}${decl}
});
}
+var allLayoutProperties = [];
+var allPaintProperties = [];
+var allTypes = [];
+
for (var layer of layers) {
+ allLayoutProperties.push(layer.layoutProperties);
+ allPaintProperties.push(layer.paintProperties);
+ allTypes.push(layer.type);
+ const containsEnumerationProperties = _.filter(layer.layoutProperties, function(property){ return property["type"] === "enum"; }).length || _.filter(layer.paintProperties, function(property){ return property["type"] === "enum"; }).length;
+ layer.containsEnumerationProperties = containsEnumerationProperties;
+
writeIfModified(`platform/darwin/src/${prefix}${camelize(layer.type)}${suffix}.h`, duplicatePlatformDecls(layerH(layer)));
writeIfModified(`platform/darwin/src/${prefix}${camelize(layer.type)}${suffix}.mm`, layerM(layer));
writeIfModified(`platform/darwin/test/${prefix}${camelize(layer.type)}${suffix}Tests.m`, testLayers(layer));
}
+
+fs.writeFileSync(`platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h`, categoryH({
+ layoutProperties: _.flatten(allLayoutProperties),
+ paintProperties: _.flatten(allPaintProperties),
+ types: allTypes
+}));
+fs.writeFileSync(`platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm`, categoryM({
+ layoutProperties: _.flatten(allLayoutProperties),
+ paintProperties: _.flatten(allPaintProperties)
+}));
diff --git a/platform/darwin/scripts/style-spec-cocoa-conventions-v8.json b/platform/darwin/scripts/style-spec-cocoa-conventions-v8.json
new file mode 100644
index 0000000000..e37598406b
--- /dev/null
+++ b/platform/darwin/scripts/style-spec-cocoa-conventions-v8.json
@@ -0,0 +1,9 @@
+{
+ "layout_symbol": {
+ "icon-image": "icon-image-name"
+ },
+ "paint_raster": {
+ "raster-brightness-min": "minimum-raster-brightness",
+ "raster-brightness-max": "maximum-raster-brightness"
+ }
+} \ No newline at end of file
diff --git a/platform/darwin/src/MGLBackgroundStyleLayer.h b/platform/darwin/src/MGLBackgroundStyleLayer.h
index a70383cc9c..656e104bbb 100644
--- a/platform/darwin/src/MGLBackgroundStyleLayer.h
+++ b/platform/darwin/src/MGLBackgroundStyleLayer.h
@@ -39,17 +39,17 @@ NS_ASSUME_NONNULL_BEGIN
#endif
/**
- Name of image in style images to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
- */
-@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *backgroundPattern;
-
-/**
The opacity at which the background will be drawn.
The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *backgroundOpacity;
+/**
+ Name of image in style images to use for drawing an image background. For seamless patterns, image width and height must be a factor of two (2, 4, 8, ..., 512).
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *backgroundPattern;
+
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLBackgroundStyleLayer.mm b/platform/darwin/src/MGLBackgroundStyleLayer.mm
index 33a105e5d5..253414852a 100644
--- a/platform/darwin/src/MGLBackgroundStyleLayer.mm
+++ b/platform/darwin/src/MGLBackgroundStyleLayer.mm
@@ -2,6 +2,7 @@
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
#import "MGLSource.h"
+#import "MGLMapView_Private.h"
#import "NSPredicate+MGLAdditions.h"
#import "MGLStyleLayer_Private.h"
#import "MGLStyleValue_Private.h"
@@ -11,50 +12,112 @@
@interface MGLBackgroundStyleLayer ()
-@property (nonatomic) mbgl::style::BackgroundLayer *layer;
+@property (nonatomic) mbgl::style::BackgroundLayer *rawLayer;
@end
@implementation MGLBackgroundStyleLayer
+{
+ std::unique_ptr<mbgl::style::BackgroundLayer> _pendingLayer;
+}
- (instancetype)initWithIdentifier:(NSString *)identifier
{
if (self = [super initWithIdentifier:identifier]) {
- _layer = new mbgl::style::BackgroundLayer(identifier.UTF8String);
+ auto layer = std::make_unique<mbgl::style::BackgroundLayer>(identifier.UTF8String);
+ _pendingLayer = std::move(layer);
+ _rawLayer = _pendingLayer.get();
}
return self;
}
+#pragma mark - Adding to and removing from a map view
+
+- (void)addToMapView:(MGLMapView *)mapView
+{
+ if (_pendingLayer == nullptr) {
+ [NSException raise:@"MGLRedundantLayerException"
+ format:@"This instance %@ was already added to %@. Adding the same layer instance " \
+ "to the style more than once is invalid.", self, mapView.style];
+ }
+
+ [self addToMapView:mapView belowLayer:nil];
+}
+
+- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
+{
+ if (otherLayer) {
+ const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String};
+ mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId);
+ } else {
+ mapView.mbglMap->addLayer(std::move(_pendingLayer));
+ }
+}
+
+- (void)removeFromMapView:(MGLMapView *)mapView
+{
+ _pendingLayer = nullptr;
+ _rawLayer = nullptr;
+
+ auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String);
+ if (!removedLayer) {
+ return;
+ }
+
+ mbgl::style::BackgroundLayer *layer = dynamic_cast<mbgl::style::BackgroundLayer *>(removedLayer.get());
+ if (!layer) {
+ return;
+ }
+
+ removedLayer.release();
+
+ _pendingLayer = std::unique_ptr<mbgl::style::BackgroundLayer>(layer);
+ _rawLayer = _pendingLayer.get();
+}
+
#pragma mark - Accessing the Paint Attributes
- (void)setBackgroundColor:(MGLStyleValue<MGLColor *> *)backgroundColor {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(backgroundColor);
- self.layer->setBackgroundColor(mbglValue);
+ _rawLayer->setBackgroundColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)backgroundColor {
- auto propertyValue = self.layer->getBackgroundColor() ?: self.layer->getDefaultBackgroundColor();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getBackgroundColor() ?: _rawLayer->getDefaultBackgroundColor();
return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
}
+- (void)setBackgroundOpacity:(MGLStyleValue<NSNumber *> *)backgroundOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(backgroundOpacity);
+ _rawLayer->setBackgroundOpacity(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)backgroundOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getBackgroundOpacity() ?: _rawLayer->getDefaultBackgroundOpacity();
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+}
+
- (void)setBackgroundPattern:(MGLStyleValue<NSString *> *)backgroundPattern {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toPropertyValue(backgroundPattern);
- self.layer->setBackgroundPattern(mbglValue);
+ _rawLayer->setBackgroundPattern(mbglValue);
}
- (MGLStyleValue<NSString *> *)backgroundPattern {
- auto propertyValue = self.layer->getBackgroundPattern() ?: self.layer->getDefaultBackgroundPattern();
- return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue);
-}
+ MGLAssertStyleLayerIsValid();
-- (void)setBackgroundOpacity:(MGLStyleValue<NSNumber *> *)backgroundOpacity {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(backgroundOpacity);
- self.layer->setBackgroundOpacity(mbglValue);
+ auto propertyValue = _rawLayer->getBackgroundPattern() ?: _rawLayer->getDefaultBackgroundPattern();
+ return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue);
}
-- (MGLStyleValue<NSNumber *> *)backgroundOpacity {
- auto propertyValue = self.layer->getBackgroundOpacity() ?: self.layer->getDefaultBackgroundOpacity();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
-}
@end
diff --git a/platform/darwin/src/MGLCircleStyleLayer.h b/platform/darwin/src/MGLCircleStyleLayer.h
index da7076e7d1..2d88a664ba 100644
--- a/platform/darwin/src/MGLCircleStyleLayer.h
+++ b/platform/darwin/src/MGLCircleStyleLayer.h
@@ -7,35 +7,35 @@
NS_ASSUME_NONNULL_BEGIN
/**
- Controls the translation reference point.
+ Controls the scaling behavior of the circle when the map is pitched.
- Values of this type are used in the `circleTranslateAnchor` property of `MGLCircleStyleLayer`.
+ Values of this type are used in the `circlePitchScale` property of `MGLCircleStyleLayer`.
*/
-typedef NS_ENUM(NSUInteger, MGLCircleTranslateAnchor) {
+typedef NS_ENUM(NSUInteger, MGLCirclePitchScale) {
/**
- The circle is translated relative to the map.
+ Circles are scaled according to their apparent distance to the camera.
*/
- MGLCircleTranslateAnchorMap,
+ MGLCirclePitchScaleMap,
/**
- The circle is translated relative to the viewport.
+ Circles are not scaled.
*/
- MGLCircleTranslateAnchorViewport,
+ MGLCirclePitchScaleViewport,
};
/**
- Controls the scaling behavior of the circle when the map is pitched.
+ Controls the translation reference point.
- Values of this type are used in the `circlePitchScale` property of `MGLCircleStyleLayer`.
+ Values of this type are used in the `circleTranslateAnchor` property of `MGLCircleStyleLayer`.
*/
-typedef NS_ENUM(NSUInteger, MGLCirclePitchScale) {
+typedef NS_ENUM(NSUInteger, MGLCircleTranslateAnchor) {
/**
- Circles are scaled according to their apparent distance to the camera.
+ The circle is translated relative to the map.
*/
- MGLCirclePitchScaleMap,
+ MGLCircleTranslateAnchorMap,
/**
- Circles are not scaled.
+ The circle is translated relative to the viewport.
*/
- MGLCirclePitchScaleViewport,
+ MGLCircleTranslateAnchorViewport,
};
/**
@@ -49,13 +49,11 @@ typedef NS_ENUM(NSUInteger, MGLCirclePitchScale) {
#pragma mark - Accessing the Paint Attributes
/**
- Circle radius.
-
- This property is measured in points.
+ Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `5`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleRadius;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleBlur;
#if TARGET_OS_IPHONE
/**
@@ -74,18 +72,27 @@ typedef NS_ENUM(NSUInteger, MGLCirclePitchScale) {
#endif
/**
- Amount to blur the circle. 1 blurs the circle such that only the centerpoint is full opacity.
+ The opacity at which the circle will be drawn.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleBlur;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleOpacity;
/**
- The opacity at which the circle will be drawn.
+ Controls the scaling behavior of the circle when the map is pitched.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLCirclePitchScaleMap`. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleOpacity;
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *circlePitchScale;
+
+/**
+ Circle radius.
+
+ This property is measured in points.
+
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `5`. Set this property to `nil` to reset it to the default value.
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *circleRadius;
/**
The geometry's offset.
@@ -105,13 +112,6 @@ typedef NS_ENUM(NSUInteger, MGLCirclePitchScale) {
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *circleTranslateAnchor;
-/**
- Controls the scaling behavior of the circle when the map is pitched.
-
- The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLCirclePitchScaleMap`. Set this property to `nil` to reset it to the default value.
- */
-@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *circlePitchScale;
-
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLCircleStyleLayer.mm b/platform/darwin/src/MGLCircleStyleLayer.mm
index 8fe97a0537..91f91a7bcd 100644
--- a/platform/darwin/src/MGLCircleStyleLayer.mm
+++ b/platform/darwin/src/MGLCircleStyleLayer.mm
@@ -2,120 +2,218 @@
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
#import "MGLSource.h"
+#import "MGLMapView_Private.h"
#import "NSPredicate+MGLAdditions.h"
#import "MGLStyleLayer_Private.h"
#import "MGLStyleValue_Private.h"
#import "MGLCircleStyleLayer.h"
#include <mbgl/style/layers/circle_layer.hpp>
+namespace mbgl {
+
+ MBGL_DEFINE_ENUM(MGLCirclePitchScale, {
+ { MGLCirclePitchScaleMap, "map" },
+ { MGLCirclePitchScaleViewport, "viewport" },
+ });
+
+ MBGL_DEFINE_ENUM(MGLCircleTranslateAnchor, {
+ { MGLCircleTranslateAnchorMap, "map" },
+ { MGLCircleTranslateAnchorViewport, "viewport" },
+ });
+
+}
@interface MGLCircleStyleLayer ()
-@property (nonatomic) mbgl::style::CircleLayer *layer;
+@property (nonatomic) mbgl::style::CircleLayer *rawLayer;
@end
@implementation MGLCircleStyleLayer
+{
+ std::unique_ptr<mbgl::style::CircleLayer> _pendingLayer;
+}
- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source
{
if (self = [super initWithIdentifier:identifier source:source]) {
- _layer = new mbgl::style::CircleLayer(identifier.UTF8String, source.identifier.UTF8String);
+ auto layer = std::make_unique<mbgl::style::CircleLayer>(identifier.UTF8String, source.identifier.UTF8String);
+ _pendingLayer = std::move(layer);
+ _rawLayer = _pendingLayer.get();
}
return self;
}
-
- (NSString *)sourceLayerIdentifier
{
- auto layerID = self.layer->getSourceLayer();
+ MGLAssertStyleLayerIsValid();
+
+ auto layerID = _rawLayer->getSourceLayer();
return layerID.empty() ? nil : @(layerID.c_str());
}
- (void)setSourceLayerIdentifier:(NSString *)sourceLayerIdentifier
{
- self.layer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: "");
+ MGLAssertStyleLayerIsValid();
+
+ _rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: "");
}
- (void)setPredicate:(NSPredicate *)predicate
{
- self.layer->setFilter(predicate.mgl_filter);
+ MGLAssertStyleLayerIsValid();
+
+ _rawLayer->setFilter(predicate.mgl_filter);
}
- (NSPredicate *)predicate
{
- return [NSPredicate mgl_predicateWithFilter:self.layer->getFilter()];
+ MGLAssertStyleLayerIsValid();
+
+ return [NSPredicate mgl_predicateWithFilter:_rawLayer->getFilter()];
+}
+#pragma mark - Adding to and removing from a map view
+
+- (void)addToMapView:(MGLMapView *)mapView
+{
+ if (_pendingLayer == nullptr) {
+ [NSException raise:@"MGLRedundantLayerException"
+ format:@"This instance %@ was already added to %@. Adding the same layer instance " \
+ "to the style more than once is invalid.", self, mapView.style];
+ }
+
+ [self addToMapView:mapView belowLayer:nil];
+}
+
+- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
+{
+ if (otherLayer) {
+ const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String};
+ mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId);
+ } else {
+ mapView.mbglMap->addLayer(std::move(_pendingLayer));
+ }
+}
+
+- (void)removeFromMapView:(MGLMapView *)mapView
+{
+ _pendingLayer = nullptr;
+ _rawLayer = nullptr;
+
+ auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String);
+ if (!removedLayer) {
+ return;
+ }
+
+ mbgl::style::CircleLayer *layer = dynamic_cast<mbgl::style::CircleLayer *>(removedLayer.get());
+ if (!layer) {
+ return;
+ }
+
+ removedLayer.release();
+
+ _pendingLayer = std::unique_ptr<mbgl::style::CircleLayer>(layer);
+ _rawLayer = _pendingLayer.get();
}
#pragma mark - Accessing the Paint Attributes
-- (void)setCircleRadius:(MGLStyleValue<NSNumber *> *)circleRadius {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(circleRadius);
- self.layer->setCircleRadius(mbglValue);
+- (void)setCircleBlur:(MGLStyleValue<NSNumber *> *)circleBlur {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(circleBlur);
+ _rawLayer->setCircleBlur(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)circleRadius {
- auto propertyValue = self.layer->getCircleRadius() ?: self.layer->getDefaultCircleRadius();
+- (MGLStyleValue<NSNumber *> *)circleBlur {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getCircleBlur() ?: _rawLayer->getDefaultCircleBlur();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setCircleColor:(MGLStyleValue<MGLColor *> *)circleColor {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(circleColor);
- self.layer->setCircleColor(mbglValue);
+ _rawLayer->setCircleColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)circleColor {
- auto propertyValue = self.layer->getCircleColor() ?: self.layer->getDefaultCircleColor();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getCircleColor() ?: _rawLayer->getDefaultCircleColor();
return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
}
-- (void)setCircleBlur:(MGLStyleValue<NSNumber *> *)circleBlur {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(circleBlur);
- self.layer->setCircleBlur(mbglValue);
+- (void)setCircleOpacity:(MGLStyleValue<NSNumber *> *)circleOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(circleOpacity);
+ _rawLayer->setCircleOpacity(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)circleBlur {
- auto propertyValue = self.layer->getCircleBlur() ?: self.layer->getDefaultCircleBlur();
+- (MGLStyleValue<NSNumber *> *)circleOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getCircleOpacity() ?: _rawLayer->getDefaultCircleOpacity();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setCircleOpacity:(MGLStyleValue<NSNumber *> *)circleOpacity {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(circleOpacity);
- self.layer->setCircleOpacity(mbglValue);
+- (void)setCirclePitchScale:(MGLStyleValue<NSValue *> *)circlePitchScale {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::CirclePitchScaleType, NSValue *, mbgl::style::CirclePitchScaleType, MGLCirclePitchScale>().toEnumPropertyValue(circlePitchScale);
+ _rawLayer->setCirclePitchScale(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)circleOpacity {
- auto propertyValue = self.layer->getCircleOpacity() ?: self.layer->getDefaultCircleOpacity();
+- (MGLStyleValue<NSValue *> *)circlePitchScale {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getCirclePitchScale() ?: _rawLayer->getDefaultCirclePitchScale();
+ return MGLStyleValueTransformer<mbgl::style::CirclePitchScaleType, NSValue *, mbgl::style::CirclePitchScaleType, MGLCirclePitchScale>().toEnumStyleValue(propertyValue);
+}
+
+- (void)setCircleRadius:(MGLStyleValue<NSNumber *> *)circleRadius {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(circleRadius);
+ _rawLayer->setCircleRadius(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)circleRadius {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getCircleRadius() ?: _rawLayer->getDefaultCircleRadius();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setCircleTranslate:(MGLStyleValue<NSValue *> *)circleTranslate {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(circleTranslate);
- self.layer->setCircleTranslate(mbglValue);
+ _rawLayer->setCircleTranslate(mbglValue);
}
- (MGLStyleValue<NSValue *> *)circleTranslate {
- auto propertyValue = self.layer->getCircleTranslate() ?: self.layer->getDefaultCircleTranslate();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getCircleTranslate() ?: _rawLayer->getDefaultCircleTranslate();
return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
}
- (void)setCircleTranslateAnchor:(MGLStyleValue<NSValue *> *)circleTranslateAnchor {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *>().toPropertyValue(circleTranslateAnchor);
- self.layer->setCircleTranslateAnchor(mbglValue);
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLCircleTranslateAnchor>().toEnumPropertyValue(circleTranslateAnchor);
+ _rawLayer->setCircleTranslateAnchor(mbglValue);
}
- (MGLStyleValue<NSValue *> *)circleTranslateAnchor {
- auto propertyValue = self.layer->getCircleTranslateAnchor() ?: self.layer->getDefaultCircleTranslateAnchor();
- return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *>().toStyleValue(propertyValue);
-}
+ MGLAssertStyleLayerIsValid();
-- (void)setCirclePitchScale:(MGLStyleValue<NSValue *> *)circlePitchScale {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::CirclePitchScaleType, NSValue *>().toPropertyValue(circlePitchScale);
- self.layer->setCirclePitchScale(mbglValue);
+ auto propertyValue = _rawLayer->getCircleTranslateAnchor() ?: _rawLayer->getDefaultCircleTranslateAnchor();
+ return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLCircleTranslateAnchor>().toEnumStyleValue(propertyValue);
}
-- (MGLStyleValue<NSValue *> *)circlePitchScale {
- auto propertyValue = self.layer->getCirclePitchScale() ?: self.layer->getDefaultCirclePitchScale();
- return MGLStyleValueTransformer<mbgl::style::CirclePitchScaleType, NSValue *>().toStyleValue(propertyValue);
-}
@end
diff --git a/platform/darwin/src/MGLFillStyleLayer.h b/platform/darwin/src/MGLFillStyleLayer.h
index 799fa380c0..9bbda26ce4 100644
--- a/platform/darwin/src/MGLFillStyleLayer.h
+++ b/platform/darwin/src/MGLFillStyleLayer.h
@@ -39,13 +39,6 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslateAnchor) {
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *fillAntialias;
-/**
- The opacity of the entire fill layer. In contrast to the `fillColor`, this value will also affect the 1pt stroke around the fill, if the stroke is used.
-
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
- */
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *fillOpacity;
-
#if TARGET_OS_IPHONE
/**
The color of the filled part of this layer.
@@ -67,6 +60,13 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslateAnchor) {
#endif
/**
+ The opacity of the entire fill layer. In contrast to the `fillColor`, this value will also affect the 1pt stroke around the fill, if the stroke is used.
+
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *fillOpacity;
+
+/**
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 `fillAntialias` is set to an `MGLStyleValue` object containing an `NSNumber` object containing `YES`. Otherwise, it is ignored.
@@ -74,6 +74,11 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslateAnchor) {
@property (nonatomic, null_resettable) MGLStyleValue<MGLColor *> *fillOutlineColor;
/**
+ 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).
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *fillPattern;
+
+/**
The geometry's offset.
This property is measured in points.
@@ -91,11 +96,6 @@ typedef NS_ENUM(NSUInteger, MGLFillTranslateAnchor) {
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *fillTranslateAnchor;
-/**
- 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).
- */
-@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *fillPattern;
-
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLFillStyleLayer.mm b/platform/darwin/src/MGLFillStyleLayer.mm
index e16e3b2652..87a5144c6b 100644
--- a/platform/darwin/src/MGLFillStyleLayer.mm
+++ b/platform/darwin/src/MGLFillStyleLayer.mm
@@ -2,120 +2,213 @@
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
#import "MGLSource.h"
+#import "MGLMapView_Private.h"
#import "NSPredicate+MGLAdditions.h"
#import "MGLStyleLayer_Private.h"
#import "MGLStyleValue_Private.h"
#import "MGLFillStyleLayer.h"
#include <mbgl/style/layers/fill_layer.hpp>
+namespace mbgl {
+
+ MBGL_DEFINE_ENUM(MGLFillTranslateAnchor, {
+ { MGLFillTranslateAnchorMap, "map" },
+ { MGLFillTranslateAnchorViewport, "viewport" },
+ });
+
+}
@interface MGLFillStyleLayer ()
-@property (nonatomic) mbgl::style::FillLayer *layer;
+@property (nonatomic) mbgl::style::FillLayer *rawLayer;
@end
@implementation MGLFillStyleLayer
+{
+ std::unique_ptr<mbgl::style::FillLayer> _pendingLayer;
+}
- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source
{
if (self = [super initWithIdentifier:identifier source:source]) {
- _layer = new mbgl::style::FillLayer(identifier.UTF8String, source.identifier.UTF8String);
+ auto layer = std::make_unique<mbgl::style::FillLayer>(identifier.UTF8String, source.identifier.UTF8String);
+ _pendingLayer = std::move(layer);
+ _rawLayer = _pendingLayer.get();
}
return self;
}
-
- (NSString *)sourceLayerIdentifier
{
- auto layerID = self.layer->getSourceLayer();
+ MGLAssertStyleLayerIsValid();
+
+ auto layerID = _rawLayer->getSourceLayer();
return layerID.empty() ? nil : @(layerID.c_str());
}
- (void)setSourceLayerIdentifier:(NSString *)sourceLayerIdentifier
{
- self.layer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: "");
+ MGLAssertStyleLayerIsValid();
+
+ _rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: "");
}
- (void)setPredicate:(NSPredicate *)predicate
{
- self.layer->setFilter(predicate.mgl_filter);
+ MGLAssertStyleLayerIsValid();
+
+ _rawLayer->setFilter(predicate.mgl_filter);
}
- (NSPredicate *)predicate
{
- return [NSPredicate mgl_predicateWithFilter:self.layer->getFilter()];
+ MGLAssertStyleLayerIsValid();
+
+ return [NSPredicate mgl_predicateWithFilter:_rawLayer->getFilter()];
+}
+#pragma mark - Adding to and removing from a map view
+
+- (void)addToMapView:(MGLMapView *)mapView
+{
+ if (_pendingLayer == nullptr) {
+ [NSException raise:@"MGLRedundantLayerException"
+ format:@"This instance %@ was already added to %@. Adding the same layer instance " \
+ "to the style more than once is invalid.", self, mapView.style];
+ }
+
+ [self addToMapView:mapView belowLayer:nil];
+}
+
+- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
+{
+ if (otherLayer) {
+ const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String};
+ mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId);
+ } else {
+ mapView.mbglMap->addLayer(std::move(_pendingLayer));
+ }
+}
+
+- (void)removeFromMapView:(MGLMapView *)mapView
+{
+ _pendingLayer = nullptr;
+ _rawLayer = nullptr;
+
+ auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String);
+ if (!removedLayer) {
+ return;
+ }
+
+ mbgl::style::FillLayer *layer = dynamic_cast<mbgl::style::FillLayer *>(removedLayer.get());
+ if (!layer) {
+ return;
+ }
+
+ removedLayer.release();
+
+ _pendingLayer = std::unique_ptr<mbgl::style::FillLayer>(layer);
+ _rawLayer = _pendingLayer.get();
}
#pragma mark - Accessing the Paint Attributes
- (void)setFillAntialias:(MGLStyleValue<NSNumber *> *)fillAntialias {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(fillAntialias);
- self.layer->setFillAntialias(mbglValue);
+ _rawLayer->setFillAntialias(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)fillAntialias {
- auto propertyValue = self.layer->getFillAntialias() ?: self.layer->getDefaultFillAntialias();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getFillAntialias() ?: _rawLayer->getDefaultFillAntialias();
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
+- (void)setFillColor:(MGLStyleValue<MGLColor *> *)fillColor {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(fillColor);
+ _rawLayer->setFillColor(mbglValue);
+}
+
+- (MGLStyleValue<MGLColor *> *)fillColor {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getFillColor() ?: _rawLayer->getDefaultFillColor();
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
+}
+
- (void)setFillOpacity:(MGLStyleValue<NSNumber *> *)fillOpacity {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(fillOpacity);
- self.layer->setFillOpacity(mbglValue);
+ _rawLayer->setFillOpacity(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)fillOpacity {
- auto propertyValue = self.layer->getFillOpacity() ?: self.layer->getDefaultFillOpacity();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getFillOpacity() ?: _rawLayer->getDefaultFillOpacity();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setFillColor:(MGLStyleValue<MGLColor *> *)fillColor {
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(fillColor);
- self.layer->setFillColor(mbglValue);
+- (void)setFillOutlineColor:(MGLStyleValue<MGLColor *> *)fillOutlineColor {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(fillOutlineColor);
+ _rawLayer->setFillOutlineColor(mbglValue);
}
-- (MGLStyleValue<MGLColor *> *)fillColor {
- auto propertyValue = self.layer->getFillColor() ?: self.layer->getDefaultFillColor();
+- (MGLStyleValue<MGLColor *> *)fillOutlineColor {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getFillOutlineColor() ?: _rawLayer->getDefaultFillOutlineColor();
return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
}
-- (void)setFillOutlineColor:(MGLStyleValue<MGLColor *> *)fillOutlineColor {
- auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(fillOutlineColor);
- self.layer->setFillOutlineColor(mbglValue);
+- (void)setFillPattern:(MGLStyleValue<NSString *> *)fillPattern {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toPropertyValue(fillPattern);
+ _rawLayer->setFillPattern(mbglValue);
}
-- (MGLStyleValue<MGLColor *> *)fillOutlineColor {
- auto propertyValue = self.layer->getFillOutlineColor() ?: self.layer->getDefaultFillOutlineColor();
- return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
+- (MGLStyleValue<NSString *> *)fillPattern {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getFillPattern() ?: _rawLayer->getDefaultFillPattern();
+ return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue);
}
- (void)setFillTranslate:(MGLStyleValue<NSValue *> *)fillTranslate {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(fillTranslate);
- self.layer->setFillTranslate(mbglValue);
+ _rawLayer->setFillTranslate(mbglValue);
}
- (MGLStyleValue<NSValue *> *)fillTranslate {
- auto propertyValue = self.layer->getFillTranslate() ?: self.layer->getDefaultFillTranslate();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getFillTranslate() ?: _rawLayer->getDefaultFillTranslate();
return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
}
- (void)setFillTranslateAnchor:(MGLStyleValue<NSValue *> *)fillTranslateAnchor {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *>().toPropertyValue(fillTranslateAnchor);
- self.layer->setFillTranslateAnchor(mbglValue);
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLFillTranslateAnchor>().toEnumPropertyValue(fillTranslateAnchor);
+ _rawLayer->setFillTranslateAnchor(mbglValue);
}
- (MGLStyleValue<NSValue *> *)fillTranslateAnchor {
- auto propertyValue = self.layer->getFillTranslateAnchor() ?: self.layer->getDefaultFillTranslateAnchor();
- return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *>().toStyleValue(propertyValue);
-}
+ MGLAssertStyleLayerIsValid();
-- (void)setFillPattern:(MGLStyleValue<NSString *> *)fillPattern {
- auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toPropertyValue(fillPattern);
- self.layer->setFillPattern(mbglValue);
+ auto propertyValue = _rawLayer->getFillTranslateAnchor() ?: _rawLayer->getDefaultFillTranslateAnchor();
+ return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLFillTranslateAnchor>().toEnumStyleValue(propertyValue);
}
-- (MGLStyleValue<NSString *> *)fillPattern {
- auto propertyValue = self.layer->getFillPattern() ?: self.layer->getDefaultFillPattern();
- return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue);
-}
@end
diff --git a/platform/darwin/src/MGLForegroundStyleLayer.m b/platform/darwin/src/MGLForegroundStyleLayer.m
index e3af963313..b7a0379af2 100644
--- a/platform/darwin/src/MGLForegroundStyleLayer.m
+++ b/platform/darwin/src/MGLForegroundStyleLayer.m
@@ -10,4 +10,11 @@
return self;
}
+- (NSString *)description {
+ return [NSString stringWithFormat:
+ @"<%@: %p; identifier = %@; sourceIdentifier = %@; visible = %@>",
+ NSStringFromClass([self class]), (void *)self, self.identifier,
+ self.sourceIdentifier, self.visible ? @"YES" : @"NO"];
+}
+
@end
diff --git a/platform/darwin/src/MGLGeoJSONSource.mm b/platform/darwin/src/MGLGeoJSONSource.mm
index 0dbe1030c6..8b37ba47cd 100644
--- a/platform/darwin/src/MGLGeoJSONSource.mm
+++ b/platform/darwin/src/MGLGeoJSONSource.mm
@@ -61,9 +61,23 @@ const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionSimplificationTolerance = @"M
- (void)addToMapView:(MGLMapView *)mapView
{
+ if (_pendingSource == nullptr) {
+ [NSException raise:@"MGLRedundantSourceException"
+ format:@"This instance %@ was already added to %@. Adding the same source instance " \
+ "to the style more than once is invalid.", self, mapView.style];
+ }
+
mapView.mbglMap->addSource(std::move(_pendingSource));
}
+- (void)removeFromMapView:(MGLMapView *)mapView
+{
+ auto removedSource = mapView.mbglMap->removeSource(self.identifier.UTF8String);
+
+ _pendingSource = std::move(reinterpret_cast<std::unique_ptr<mbgl::style::GeoJSONSource> &>(removedSource));
+ self.rawSource = _pendingSource.get();
+}
+
- (void)commonInit
{
auto source = std::make_unique<mbgl::style::GeoJSONSource>(self.identifier.UTF8String, self.geoJSONOptions);
@@ -184,4 +198,10 @@ const MGLGeoJSONSourceOption MGLGeoJSONSourceOptionSimplificationTolerance = @"M
_features = MGLFeaturesFromMBGLFeatures(featureCollection);
}
+- (NSString *)description
+{
+ return [NSString stringWithFormat:@"<%@: %p; identifier = %@; URL = %@; geoJSONData = %@; features = %@>",
+ NSStringFromClass([self class]), (void *)self, self.identifier, self.URL, self.geoJSONData, self.features];
+}
+
@end
diff --git a/platform/darwin/src/MGLGeometry.h b/platform/darwin/src/MGLGeometry.h
index 5fc927697b..e2a4d818b9 100644
--- a/platform/darwin/src/MGLGeometry.h
+++ b/platform/darwin/src/MGLGeometry.h
@@ -117,11 +117,4 @@ NS_INLINE CLLocationDegrees MGLDegreesFromRadians(CGFloat radians) {
return radians * 180 / M_PI;
}
-/**
- Methods for round-tripping Mapbox geometry structure values.
- */
-@interface NSValue (MGLGeometryAdditions)
-
-@end
-
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h
index 68b0a73a2e..74d8f7bfe9 100644
--- a/platform/darwin/src/MGLLineStyleLayer.h
+++ b/platform/darwin/src/MGLLineStyleLayer.h
@@ -107,11 +107,13 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslateAnchor) {
#pragma mark - Accessing the Paint Attributes
/**
- The opacity at which the line will be drawn.
+ Blur applied to the line, in points.
+
+ This property is measured in points.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *lineOpacity;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *lineBlur;
#if TARGET_OS_IPHONE
/**
@@ -134,31 +136,13 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslateAnchor) {
#endif
/**
- The geometry's offset.
-
- This property is measured in points.
-
- The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 points from the left and 0 points from the top. Set this property to `nil` to reset it to the default value.
- */
-@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *lineTranslate;
-
-/**
- Controls the translation reference point.
-
- The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLLineTranslateAnchorMap`. Set this property to `nil` to reset it to the default value.
-
- This property is only applied to the style if `lineTranslate` is non-`nil`. Otherwise, it is ignored.
- */
-@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *lineTranslateAnchor;
+ 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 points, multiply the length by the current line width.
-/**
- Stroke thickness.
+ This property is measured in line widths.
- This property is measured in points.
-
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
+ This property is only applied to the style if `linePattern` is set to `nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *lineWidth;
+@property (nonatomic, null_resettable) MGLStyleValue<NSArray<NSNumber *> *> *lineDasharray;
/**
Draws a line casing outside of a line's actual path. Value indicates the width of the inner gap.
@@ -179,27 +163,43 @@ typedef NS_ENUM(NSUInteger, MGLLineTranslateAnchor) {
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *lineOffset;
/**
- Blur applied to the line, in points.
+ The opacity at which the line will be drawn.
+
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *lineOpacity;
+
+/**
+ Name of image in style images to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512).
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *linePattern;
+
+/**
+ The geometry's offset.
This property is measured in points.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 points from the left and 0 points from the top. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *lineBlur;
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *lineTranslate;
/**
- 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 points, multiply the length by the current line width.
-
- This property is measured in line widths.
+ Controls the translation reference point.
+
+ The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLLineTranslateAnchorMap`. 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.
+ This property is only applied to the style if `lineTranslate` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSArray<NSNumber *> *> *lineDasharray;
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *lineTranslateAnchor;
/**
- Name of image in style images to use for drawing image lines. For seamless patterns, image width must be a factor of two (2, 4, 8, ..., 512).
+ Stroke thickness.
+
+ This property is measured in points.
+
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *linePattern;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *lineWidth;
@end
diff --git a/platform/darwin/src/MGLLineStyleLayer.mm b/platform/darwin/src/MGLLineStyleLayer.mm
index 57724a0600..b155ec65d6 100644
--- a/platform/darwin/src/MGLLineStyleLayer.mm
+++ b/platform/darwin/src/MGLLineStyleLayer.mm
@@ -2,192 +2,325 @@
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
#import "MGLSource.h"
+#import "MGLMapView_Private.h"
#import "NSPredicate+MGLAdditions.h"
#import "MGLStyleLayer_Private.h"
#import "MGLStyleValue_Private.h"
#import "MGLLineStyleLayer.h"
#include <mbgl/style/layers/line_layer.hpp>
+namespace mbgl {
+
+ MBGL_DEFINE_ENUM(MGLLineCap, {
+ { MGLLineCapButt, "butt" },
+ { MGLLineCapRound, "round" },
+ { MGLLineCapSquare, "square" },
+ });
+
+ MBGL_DEFINE_ENUM(MGLLineJoin, {
+ { MGLLineJoinBevel, "bevel" },
+ { MGLLineJoinRound, "round" },
+ { MGLLineJoinMiter, "miter" },
+ });
+
+ MBGL_DEFINE_ENUM(MGLLineTranslateAnchor, {
+ { MGLLineTranslateAnchorMap, "map" },
+ { MGLLineTranslateAnchorViewport, "viewport" },
+ });
+
+}
@interface MGLLineStyleLayer ()
-@property (nonatomic) mbgl::style::LineLayer *layer;
+@property (nonatomic) mbgl::style::LineLayer *rawLayer;
@end
@implementation MGLLineStyleLayer
+{
+ std::unique_ptr<mbgl::style::LineLayer> _pendingLayer;
+}
- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source
{
if (self = [super initWithIdentifier:identifier source:source]) {
- _layer = new mbgl::style::LineLayer(identifier.UTF8String, source.identifier.UTF8String);
+ auto layer = std::make_unique<mbgl::style::LineLayer>(identifier.UTF8String, source.identifier.UTF8String);
+ _pendingLayer = std::move(layer);
+ _rawLayer = _pendingLayer.get();
}
return self;
}
-
- (NSString *)sourceLayerIdentifier
{
- auto layerID = self.layer->getSourceLayer();
+ MGLAssertStyleLayerIsValid();
+
+ auto layerID = _rawLayer->getSourceLayer();
return layerID.empty() ? nil : @(layerID.c_str());
}
- (void)setSourceLayerIdentifier:(NSString *)sourceLayerIdentifier
{
- self.layer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: "");
+ MGLAssertStyleLayerIsValid();
+
+ _rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: "");
}
- (void)setPredicate:(NSPredicate *)predicate
{
- self.layer->setFilter(predicate.mgl_filter);
+ MGLAssertStyleLayerIsValid();
+
+ _rawLayer->setFilter(predicate.mgl_filter);
}
- (NSPredicate *)predicate
{
- return [NSPredicate mgl_predicateWithFilter:self.layer->getFilter()];
+ MGLAssertStyleLayerIsValid();
+
+ return [NSPredicate mgl_predicateWithFilter:_rawLayer->getFilter()];
+}
+#pragma mark - Adding to and removing from a map view
+
+- (void)addToMapView:(MGLMapView *)mapView
+{
+ if (_pendingLayer == nullptr) {
+ [NSException raise:@"MGLRedundantLayerException"
+ format:@"This instance %@ was already added to %@. Adding the same layer instance " \
+ "to the style more than once is invalid.", self, mapView.style];
+ }
+
+ [self addToMapView:mapView belowLayer:nil];
+}
+
+- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
+{
+ if (otherLayer) {
+ const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String};
+ mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId);
+ } else {
+ mapView.mbglMap->addLayer(std::move(_pendingLayer));
+ }
+}
+
+- (void)removeFromMapView:(MGLMapView *)mapView
+{
+ _pendingLayer = nullptr;
+ _rawLayer = nullptr;
+
+ auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String);
+ if (!removedLayer) {
+ return;
+ }
+
+ mbgl::style::LineLayer *layer = dynamic_cast<mbgl::style::LineLayer *>(removedLayer.get());
+ if (!layer) {
+ return;
+ }
+
+ removedLayer.release();
+
+ _pendingLayer = std::unique_ptr<mbgl::style::LineLayer>(layer);
+ _rawLayer = _pendingLayer.get();
}
#pragma mark - Accessing the Layout Attributes
- (void)setLineCap:(MGLStyleValue<NSValue *> *)lineCap {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::LineCapType, NSValue *>().toPropertyValue(lineCap);
- self.layer->setLineCap(mbglValue);
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::LineCapType, NSValue *, mbgl::style::LineCapType, MGLLineCap>().toEnumPropertyValue(lineCap);
+ _rawLayer->setLineCap(mbglValue);
}
- (MGLStyleValue<NSValue *> *)lineCap {
- auto propertyValue = self.layer->getLineCap() ?: self.layer->getDefaultLineCap();
- return MGLStyleValueTransformer<mbgl::style::LineCapType, NSValue *>().toStyleValue(propertyValue);
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getLineCap() ?: _rawLayer->getDefaultLineCap();
+ return MGLStyleValueTransformer<mbgl::style::LineCapType, NSValue *, mbgl::style::LineCapType, MGLLineCap>().toEnumStyleValue(propertyValue);
}
- (void)setLineJoin:(MGLStyleValue<NSValue *> *)lineJoin {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::LineJoinType, NSValue *>().toPropertyValue(lineJoin);
- self.layer->setLineJoin(mbglValue);
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::LineJoinType, NSValue *, mbgl::style::LineJoinType, MGLLineJoin>().toEnumPropertyValue(lineJoin);
+ _rawLayer->setLineJoin(mbglValue);
}
- (MGLStyleValue<NSValue *> *)lineJoin {
- auto propertyValue = self.layer->getLineJoin() ?: self.layer->getDefaultLineJoin();
- return MGLStyleValueTransformer<mbgl::style::LineJoinType, NSValue *>().toStyleValue(propertyValue);
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getLineJoin() ?: _rawLayer->getDefaultLineJoin();
+ return MGLStyleValueTransformer<mbgl::style::LineJoinType, NSValue *, mbgl::style::LineJoinType, MGLLineJoin>().toEnumStyleValue(propertyValue);
}
- (void)setLineMiterLimit:(MGLStyleValue<NSNumber *> *)lineMiterLimit {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineMiterLimit);
- self.layer->setLineMiterLimit(mbglValue);
+ _rawLayer->setLineMiterLimit(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)lineMiterLimit {
- auto propertyValue = self.layer->getLineMiterLimit() ?: self.layer->getDefaultLineMiterLimit();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getLineMiterLimit() ?: _rawLayer->getDefaultLineMiterLimit();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setLineRoundLimit:(MGLStyleValue<NSNumber *> *)lineRoundLimit {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineRoundLimit);
- self.layer->setLineRoundLimit(mbglValue);
+ _rawLayer->setLineRoundLimit(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)lineRoundLimit {
- auto propertyValue = self.layer->getLineRoundLimit() ?: self.layer->getDefaultLineRoundLimit();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getLineRoundLimit() ?: _rawLayer->getDefaultLineRoundLimit();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
#pragma mark - Accessing the Paint Attributes
-- (void)setLineOpacity:(MGLStyleValue<NSNumber *> *)lineOpacity {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineOpacity);
- self.layer->setLineOpacity(mbglValue);
+- (void)setLineBlur:(MGLStyleValue<NSNumber *> *)lineBlur {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineBlur);
+ _rawLayer->setLineBlur(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)lineOpacity {
- auto propertyValue = self.layer->getLineOpacity() ?: self.layer->getDefaultLineOpacity();
+- (MGLStyleValue<NSNumber *> *)lineBlur {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getLineBlur() ?: _rawLayer->getDefaultLineBlur();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setLineColor:(MGLStyleValue<MGLColor *> *)lineColor {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(lineColor);
- self.layer->setLineColor(mbglValue);
+ _rawLayer->setLineColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)lineColor {
- auto propertyValue = self.layer->getLineColor() ?: self.layer->getDefaultLineColor();
- return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
-}
-
-- (void)setLineTranslate:(MGLStyleValue<NSValue *> *)lineTranslate {
- auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(lineTranslate);
- self.layer->setLineTranslate(mbglValue);
-}
+ MGLAssertStyleLayerIsValid();
-- (MGLStyleValue<NSValue *> *)lineTranslate {
- auto propertyValue = self.layer->getLineTranslate() ?: self.layer->getDefaultLineTranslate();
- return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
+ auto propertyValue = _rawLayer->getLineColor() ?: _rawLayer->getDefaultLineColor();
+ return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
}
-- (void)setLineTranslateAnchor:(MGLStyleValue<NSValue *> *)lineTranslateAnchor {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *>().toPropertyValue(lineTranslateAnchor);
- self.layer->setLineTranslateAnchor(mbglValue);
-}
+- (void)setLineDasharray:(MGLStyleValue<NSArray<NSNumber *> *> *)lineDasharray {
+ MGLAssertStyleLayerIsValid();
-- (MGLStyleValue<NSValue *> *)lineTranslateAnchor {
- auto propertyValue = self.layer->getLineTranslateAnchor() ?: self.layer->getDefaultLineTranslateAnchor();
- return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *>().toStyleValue(propertyValue);
+ auto mbglValue = MGLStyleValueTransformer<std::vector<float>, NSArray<NSNumber *> *, float>().toPropertyValue(lineDasharray);
+ _rawLayer->setLineDasharray(mbglValue);
}
-- (void)setLineWidth:(MGLStyleValue<NSNumber *> *)lineWidth {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineWidth);
- self.layer->setLineWidth(mbglValue);
-}
+- (MGLStyleValue<NSArray<NSNumber *> *> *)lineDasharray {
+ MGLAssertStyleLayerIsValid();
-- (MGLStyleValue<NSNumber *> *)lineWidth {
- auto propertyValue = self.layer->getLineWidth() ?: self.layer->getDefaultLineWidth();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ auto propertyValue = _rawLayer->getLineDasharray() ?: _rawLayer->getDefaultLineDasharray();
+ return MGLStyleValueTransformer<std::vector<float>, NSArray<NSNumber *> *, float>().toStyleValue(propertyValue);
}
- (void)setLineGapWidth:(MGLStyleValue<NSNumber *> *)lineGapWidth {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineGapWidth);
- self.layer->setLineGapWidth(mbglValue);
+ _rawLayer->setLineGapWidth(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)lineGapWidth {
- auto propertyValue = self.layer->getLineGapWidth() ?: self.layer->getDefaultLineGapWidth();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getLineGapWidth() ?: _rawLayer->getDefaultLineGapWidth();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setLineOffset:(MGLStyleValue<NSNumber *> *)lineOffset {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineOffset);
- self.layer->setLineOffset(mbglValue);
+ _rawLayer->setLineOffset(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)lineOffset {
- auto propertyValue = self.layer->getLineOffset() ?: self.layer->getDefaultLineOffset();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getLineOffset() ?: _rawLayer->getDefaultLineOffset();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setLineBlur:(MGLStyleValue<NSNumber *> *)lineBlur {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineBlur);
- self.layer->setLineBlur(mbglValue);
-}
+- (void)setLineOpacity:(MGLStyleValue<NSNumber *> *)lineOpacity {
+ MGLAssertStyleLayerIsValid();
-- (MGLStyleValue<NSNumber *> *)lineBlur {
- auto propertyValue = self.layer->getLineBlur() ?: self.layer->getDefaultLineBlur();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineOpacity);
+ _rawLayer->setLineOpacity(mbglValue);
}
-- (void)setLineDasharray:(MGLStyleValue<NSArray<NSNumber *> *> *)lineDasharray {
- auto mbglValue = MGLStyleValueTransformer<std::vector<float>, NSArray<NSNumber *> *, float>().toPropertyValue(lineDasharray);
- self.layer->setLineDasharray(mbglValue);
-}
+- (MGLStyleValue<NSNumber *> *)lineOpacity {
+ MGLAssertStyleLayerIsValid();
-- (MGLStyleValue<NSArray<NSNumber *> *> *)lineDasharray {
- auto propertyValue = self.layer->getLineDasharray() ?: self.layer->getDefaultLineDasharray();
- return MGLStyleValueTransformer<std::vector<float>, NSArray<NSNumber *> *, float>().toStyleValue(propertyValue);
+ auto propertyValue = _rawLayer->getLineOpacity() ?: _rawLayer->getDefaultLineOpacity();
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setLinePattern:(MGLStyleValue<NSString *> *)linePattern {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toPropertyValue(linePattern);
- self.layer->setLinePattern(mbglValue);
+ _rawLayer->setLinePattern(mbglValue);
}
- (MGLStyleValue<NSString *> *)linePattern {
- auto propertyValue = self.layer->getLinePattern() ?: self.layer->getDefaultLinePattern();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getLinePattern() ?: _rawLayer->getDefaultLinePattern();
return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue);
}
+- (void)setLineTranslate:(MGLStyleValue<NSValue *> *)lineTranslate {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(lineTranslate);
+ _rawLayer->setLineTranslate(mbglValue);
+}
+
+- (MGLStyleValue<NSValue *> *)lineTranslate {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getLineTranslate() ?: _rawLayer->getDefaultLineTranslate();
+ return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
+}
+
+- (void)setLineTranslateAnchor:(MGLStyleValue<NSValue *> *)lineTranslateAnchor {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLLineTranslateAnchor>().toEnumPropertyValue(lineTranslateAnchor);
+ _rawLayer->setLineTranslateAnchor(mbglValue);
+}
+
+- (MGLStyleValue<NSValue *> *)lineTranslateAnchor {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getLineTranslateAnchor() ?: _rawLayer->getDefaultLineTranslateAnchor();
+ return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLLineTranslateAnchor>().toEnumStyleValue(propertyValue);
+}
+
+- (void)setLineWidth:(MGLStyleValue<NSNumber *> *)lineWidth {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(lineWidth);
+ _rawLayer->setLineWidth(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)lineWidth {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getLineWidth() ?: _rawLayer->getDefaultLineWidth();
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+}
+
+
@end
diff --git a/platform/darwin/src/MGLMultiPoint.h b/platform/darwin/src/MGLMultiPoint.h
index 69c7295842..3431fc2483 100644
--- a/platform/darwin/src/MGLMultiPoint.h
+++ b/platform/darwin/src/MGLMultiPoint.h
@@ -48,16 +48,25 @@ NS_ASSUME_NONNULL_BEGIN
cause the shape to be redrawn if it is currently visible on the map.
@param range The range of points to update. The `location` field indicates the
- first point you are replacing, with `0` being the first point, `1` being
- the second point, and so on. The `length` field indicates the number of
- points to update. You can append to an existing array of coordinates
- by specifying a range with a `location` at the end of the existing array
- and/or a `length` which extends past the end of the existing array. The array
- in _`coords`_ must be equal in number to the length of the range.
+ first point you are replacing, with `0` being the first point, `1` being
+ the second point, and so on. The `length` field indicates the number of
+ points to update. The array in _`coords`_ must be equal in number to the
+ length of the range. If you want to append to the existing coordinates
+ array use `-[MGLMultiPoint appendCoordinates:count:]`.
@param coords The array of coordinates defining the shape. The data in this
- array is copied to the object.
+ array is copied to the object.
+ */
+- (void)replaceCoordinatesInRange:(NSRange)range withCoordinates:(const CLLocationCoordinate2D *)coords;
+
+/**
+ Appends one or more coordinates for the shape, which will instantaneously
+ cause the shape to be redrawn if it is currently visible on the map.
+
+ @param coords The array of coordinates to add to the shape. The data in this
+ array is copied to the new object.
+ @param count The number of items in the `coords` array.
*/
-- (void)replaceCoordinatesInRange:(NSRange)range withCoordinates:(CLLocationCoordinate2D *)coords;
+- (void)appendCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count;
@end
diff --git a/platform/darwin/src/MGLMultiPoint.mm b/platform/darwin/src/MGLMultiPoint.mm
index 17a61ed081..57b57889f3 100644
--- a/platform/darwin/src/MGLMultiPoint.mm
+++ b/platform/darwin/src/MGLMultiPoint.mm
@@ -14,55 +14,33 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor)
@implementation MGLMultiPoint
{
- size_t _count;
MGLCoordinateBounds _bounds;
+ std::vector<CLLocationCoordinate2D> _coordinates;
}
-- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count
+- (instancetype)initWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count
{
self = [super init];
if (self)
{
- [self setupWithCoordinates:coords count:count];
+ NSAssert(count > 0, @"A multipoint must have coordinates");
+ _coordinates = { coords, coords + count };
+ [self computeBounds];
}
return self;
}
-- (void)setupWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count
-{
- if (_coordinates) free(_coordinates);
-
- _count = count;
- _coordinates = (CLLocationCoordinate2D *)malloc(_count * sizeof(CLLocationCoordinate2D));
-
- mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty();
-
- for (NSUInteger i = 0; i < _count; i++)
- {
- _coordinates[i] = coords[i];
- bounds.extend(mbgl::LatLng(coords[i].latitude, coords[i].longitude));
- }
-
- _bounds = MGLCoordinateBoundsFromLatLngBounds(bounds);
-}
-
-- (void)dealloc
-{
- free(_coordinates);
-}
-
- (CLLocationCoordinate2D)coordinate
{
- assert(_count > 0);
-
- return CLLocationCoordinate2DMake(_coordinates[0].latitude, _coordinates[0].longitude);
+ NSAssert([self pointCount] > 0, @"A multipoint must have coordinates");
+ return _coordinates.at(0);
}
- (NSUInteger)pointCount
{
- return _count;
+ return _coordinates.size();
}
+ (NS_SET_OF(NSString *) *)keyPathsForValuesAffectingPointCount
@@ -70,59 +48,59 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor)
return [NSSet setWithObjects:@"coordinates", nil];
}
+- (CLLocationCoordinate2D *)coordinates
+{
+ return _coordinates.data();
+}
+
- (void)getCoordinates:(CLLocationCoordinate2D *)coords range:(NSRange)range
{
- if (range.location + range.length > _count)
+ if (range.location + range.length > [self pointCount])
{
[NSException raise:NSRangeException
- format:@"Invalid coordinate range %@ extends beyond current coordinate count of %zu",
- NSStringFromRange(range), _count];
+ format:@"Invalid coordinate range %@ extends beyond current coordinate count of %ld",
+ NSStringFromRange(range), (unsigned long)[self pointCount]];
}
- NSUInteger index = 0;
+ std::copy(_coordinates.begin() + range.location, _coordinates.begin() + NSMaxRange(range), coords);
+}
- for (NSUInteger i = range.location; i < range.location + range.length; i++)
- {
- coords[index] = _coordinates[i];
- index++;
- }
+- (void)appendCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count
+{
+ [self willChangeValueForKey:@"coordinates"];
+ _coordinates.insert(_coordinates.end(), count, *coords);
+ [self computeBounds];
+ [self didChangeValueForKey:@"coordinates"];
}
-- (void)replaceCoordinatesInRange:(NSRange)range withCoordinates:(CLLocationCoordinate2D *)coords
+- (void)replaceCoordinatesInRange:(NSRange)range withCoordinates:(const CLLocationCoordinate2D *)coords
{
- if ((coords >= _coordinates && coords < _coordinates + _count) ||
- (coords + range.length >= _coordinates && coords + range.length < _coordinates + _count))
- {
- [NSException raise:NSRangeException format:@"Reuse of existing coordinates array %p not supported", coords];
- }
- else if (range.length == 0)
+ if (range.length == 0)
{
- [NSException raise:NSRangeException format:@"Empty coordinate range %@", NSStringFromRange(range)];
+ return;
}
- else if (range.location > _count)
+
+ if (NSMaxRange(range) > _coordinates.size())
{
[NSException raise:NSRangeException
- format:@"Invalid range %@ for existing coordinate count %zu",
- NSStringFromRange(range), _count];
+ format:@"Invalid range %@ for existing coordinate count %ld",
+ NSStringFromRange(range), (unsigned long)[self pointCount]];
}
[self willChangeValueForKey:@"coordinates"];
- if (NSMaxRange(range) <= _count)
- {
- // replacing existing coordinate(s)
- memcpy(_coordinates + range.location, coords, range.length * sizeof(CLLocationCoordinate2D));
- }
- else
+ std::copy(coords, coords + range.length, _coordinates.begin() + range.location);
+ [self computeBounds];
+ [self didChangeValueForKey:@"coordinates"];
+}
+
+- (void)computeBounds
+{
+ mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty();
+ for (auto coordinate : _coordinates)
{
- // appending new coordinate(s)
- NSUInteger newCount = NSMaxRange(range);
- CLLocationCoordinate2D *newCoordinates = (CLLocationCoordinate2D *)malloc(newCount * sizeof(CLLocationCoordinate2D));
- memcpy(newCoordinates, _coordinates, fmin(_count, range.location) * sizeof(CLLocationCoordinate2D));
- memcpy(newCoordinates + range.location, coords, range.length * sizeof(CLLocationCoordinate2D));
- [self setupWithCoordinates:newCoordinates count:newCount];
- free(newCoordinates);
+ bounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude));
}
- [self didChangeValueForKey:@"coordinates"];
+ _bounds = MGLCoordinateBoundsFromLatLngBounds(bounds);
}
- (MGLCoordinateBounds)overlayBounds
@@ -144,7 +122,7 @@ mbgl::Color MGLColorObjectFromCGColorRef(CGColorRef cgColor)
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p; count = %lu; bounds = %@>",
- NSStringFromClass([self class]), (void *)self, (unsigned long)_count, MGLStringFromCoordinateBounds(_bounds)];
+ NSStringFromClass([self class]), (void *)self, (unsigned long)[self pointCount], MGLStringFromCoordinateBounds(_bounds)];
}
@end
diff --git a/platform/darwin/src/MGLMultiPoint_Private.h b/platform/darwin/src/MGLMultiPoint_Private.h
index 7bc3cae58a..a9b4b72ca5 100644
--- a/platform/darwin/src/MGLMultiPoint_Private.h
+++ b/platform/darwin/src/MGLMultiPoint_Private.h
@@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface MGLMultiPoint (Private)
-- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count;
+- (instancetype)initWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count;
- (BOOL)intersectsOverlayBounds:(MGLCoordinateBounds)overlayBounds;
/** Constructs a shape annotation object, asking the delegate for style values. */
diff --git a/platform/darwin/src/MGLPointCollection.h b/platform/darwin/src/MGLPointCollection.h
index db497d0a52..ce3e95a16d 100644
--- a/platform/darwin/src/MGLPointCollection.h
+++ b/platform/darwin/src/MGLPointCollection.h
@@ -26,7 +26,7 @@
@param count The number of items in the `coords` array.
@return A new point collection object.
*/
-+ (instancetype)pointCollectionWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count;
++ (instancetype)pointCollectionWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count;
/** The array of coordinates associated with the shape. */
@property (nonatomic, readonly) CLLocationCoordinate2D *coordinates NS_RETURNS_INNER_POINTER;
diff --git a/platform/darwin/src/MGLPointCollection.mm b/platform/darwin/src/MGLPointCollection.mm
index 5871915b5d..ab4a9c978e 100644
--- a/platform/darwin/src/MGLPointCollection.mm
+++ b/platform/darwin/src/MGLPointCollection.mm
@@ -8,31 +8,26 @@ NS_ASSUME_NONNULL_BEGIN
@implementation MGLPointCollection
{
- size_t _count;
MGLCoordinateBounds _bounds;
+ std::vector<CLLocationCoordinate2D> _coordinates;
}
-+ (instancetype)pointCollectionWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count
++ (instancetype)pointCollectionWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count
{
return [[self alloc] initWithCoordinates:coords count:count];
}
-- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count
+- (instancetype)initWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count
{
self = [super init];
if (self)
{
- _count = count;
- _coordinates = (CLLocationCoordinate2D *)malloc(_count * sizeof(CLLocationCoordinate2D));
-
+ _coordinates = { coords, coords + count };
mbgl::LatLngBounds bounds = mbgl::LatLngBounds::empty();
-
- for (NSUInteger i = 0; i < count; i++)
+ for (auto coordinate : _coordinates)
{
- _coordinates[i] = coords[i];
- bounds.extend(mbgl::LatLng(coords[i].latitude, coords[i].longitude));
+ bounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude));
}
-
_bounds = MGLCoordinateBoundsFromLatLngBounds(bounds);
}
return self;
@@ -40,32 +35,30 @@ NS_ASSUME_NONNULL_BEGIN
- (NSUInteger)pointCount
{
- return _count;
+ return _coordinates.size();
+}
+
+- (CLLocationCoordinate2D *)coordinates
+{
+ return _coordinates.data();
}
- (CLLocationCoordinate2D)coordinate
{
- assert(_count > 0);
-
- return CLLocationCoordinate2DMake(_coordinates[0].latitude, _coordinates[0].longitude);
+ NSAssert([self pointCount] > 0, @"A multipoint must have coordinates");
+ return _coordinates.at(0);
}
- (void)getCoordinates:(CLLocationCoordinate2D *)coords range:(NSRange)range
{
- if (range.location + range.length > _count)
+ if (range.location + range.length > [self pointCount])
{
[NSException raise:NSRangeException
- format:@"Invalid coordinate range %@ extends beyond current coordinate count of %zu",
- NSStringFromRange(range), _count];
- }
-
- NSUInteger index = 0;
-
- for (NSUInteger i = range.location; i < range.location + range.length; i++)
- {
- coords[index] = _coordinates[i];
- index++;
+ format:@"Invalid coordinate range %@ extends beyond current coordinate count of %ld",
+ NSStringFromRange(range), (unsigned long)[self pointCount]];
}
+
+ std::copy(_coordinates.begin() + range.location, _coordinates.begin() + NSMaxRange(range), coords);
}
- (MGLCoordinateBounds)overlayBounds
@@ -104,7 +97,7 @@ NS_ASSUME_NONNULL_BEGIN
- (NSString *)description
{
return [NSString stringWithFormat:@"<%@: %p; count = %lu>",
- NSStringFromClass([self class]), (void *)self, (unsigned long)_count];
+ NSStringFromClass([self class]), (void *)self, (unsigned long)[self pointCount]];
}
@end
diff --git a/platform/darwin/src/MGLPointCollection_Private.h b/platform/darwin/src/MGLPointCollection_Private.h
index 039c1f18be..fc1c33fe4c 100644
--- a/platform/darwin/src/MGLPointCollection_Private.h
+++ b/platform/darwin/src/MGLPointCollection_Private.h
@@ -4,7 +4,7 @@ NS_ASSUME_NONNULL_BEGIN
@interface MGLPointCollection (Private)
-- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count;
+- (instancetype)initWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count;
@end
diff --git a/platform/darwin/src/MGLPolygon.h b/platform/darwin/src/MGLPolygon.h
index 3d5b36abb6..b9ec6b8399 100644
--- a/platform/darwin/src/MGLPolygon.h
+++ b/platform/darwin/src/MGLPolygon.h
@@ -36,7 +36,7 @@ NS_ASSUME_NONNULL_BEGIN
@param count The number of items in the `coords` array.
@return A new polygon object.
*/
-+ (instancetype)polygonWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count;
++ (instancetype)polygonWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count;
/**
Creates and returns an `MGLPolygon` object from the specified set of
@@ -50,7 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
is considered to have no interior polygons.
@return A new polygon object.
*/
-+ (instancetype)polygonWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count interiorPolygons:(nullable NS_ARRAY_OF(MGLPolygon *) *)interiorPolygons;
++ (instancetype)polygonWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count interiorPolygons:(nullable NS_ARRAY_OF(MGLPolygon *) *)interiorPolygons;
@end
diff --git a/platform/darwin/src/MGLPolygon.mm b/platform/darwin/src/MGLPolygon.mm
index eae2cfe75a..7562db6e61 100644
--- a/platform/darwin/src/MGLPolygon.mm
+++ b/platform/darwin/src/MGLPolygon.mm
@@ -9,15 +9,15 @@
@dynamic overlayBounds;
-+ (instancetype)polygonWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count {
++ (instancetype)polygonWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count {
return [self polygonWithCoordinates:coords count:count interiorPolygons:nil];
}
-+ (instancetype)polygonWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count interiorPolygons:(NSArray<MGLPolygon *> *)interiorPolygons {
++ (instancetype)polygonWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count interiorPolygons:(NSArray<MGLPolygon *> *)interiorPolygons {
return [[self alloc] initWithCoordinates:coords count:count interiorPolygons:interiorPolygons];
}
-- (instancetype)initWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count interiorPolygons:(NSArray<MGLPolygon *> *)interiorPolygons {
+- (instancetype)initWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count interiorPolygons:(NSArray<MGLPolygon *> *)interiorPolygons {
if (self = [super initWithCoordinates:coords count:count]) {
if (interiorPolygons.count) {
_interiorPolygons = interiorPolygons;
diff --git a/platform/darwin/src/MGLPolyline.h b/platform/darwin/src/MGLPolyline.h
index d0274b44e3..cb98df9a1b 100644
--- a/platform/darwin/src/MGLPolyline.h
+++ b/platform/darwin/src/MGLPolyline.h
@@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN
@param count The number of items in the `coords` array.
@return A new polyline object.
*/
-+ (instancetype)polylineWithCoordinates:(CLLocationCoordinate2D *)coords count:(NSUInteger)count;
++ (instancetype)polylineWithCoordinates:(const CLLocationCoordinate2D *)coords count:(NSUInteger)count;
@end
diff --git a/platform/darwin/src/MGLPolyline.mm b/platform/darwin/src/MGLPolyline.mm
index dd2fccf53d..1801dfd44e 100644
--- a/platform/darwin/src/MGLPolyline.mm
+++ b/platform/darwin/src/MGLPolyline.mm
@@ -9,7 +9,7 @@
@dynamic overlayBounds;
-+ (instancetype)polylineWithCoordinates:(CLLocationCoordinate2D *)coords
++ (instancetype)polylineWithCoordinates:(const CLLocationCoordinate2D *)coords
count:(NSUInteger)count
{
return [[self alloc] initWithCoordinates:coords count:count];
diff --git a/platform/darwin/src/MGLRasterSource.mm b/platform/darwin/src/MGLRasterSource.mm
index fc47c23853..62472050e3 100644
--- a/platform/darwin/src/MGLRasterSource.mm
+++ b/platform/darwin/src/MGLRasterSource.mm
@@ -62,7 +62,29 @@
- (void)addToMapView:(MGLMapView *)mapView
{
+ if (_pendingSource == nullptr) {
+ [NSException raise:@"MGLRedundantSourceException"
+ format:@"This instance %@ was already added to %@. Adding the same source instance " \
+ "to the style more than once is invalid.", self, mapView.style];
+ }
+
mapView.mbglMap->addSource(std::move(_pendingSource));
}
+- (void)removeFromMapView:(MGLMapView *)mapView
+{
+ auto removedSource = mapView.mbglMap->removeSource(self.identifier.UTF8String);
+
+ _pendingSource = std::move(reinterpret_cast<std::unique_ptr<mbgl::style::RasterSource> &>(removedSource));
+ self.rawSource = _pendingSource.get();
+}
+
+- (NSString *)description
+{
+ return [NSString stringWithFormat:
+ @"<%@: %p; identifier = %@; URL = %@; tileSet = %@; tileSize = %lu>",
+ NSStringFromClass([self class]), (void *)self, self.identifier, self.URL,
+ self.tileSet, (unsigned long)self.tileSize];
+}
+
@end
diff --git a/platform/darwin/src/MGLRasterStyleLayer.h b/platform/darwin/src/MGLRasterStyleLayer.h
index afae85001e..68b187a908 100644
--- a/platform/darwin/src/MGLRasterStyleLayer.h
+++ b/platform/darwin/src/MGLRasterStyleLayer.h
@@ -17,57 +17,57 @@ NS_ASSUME_NONNULL_BEGIN
#pragma mark - Accessing the Paint Attributes
/**
- The opacity at which the image will be drawn.
+ Increase or reduce the brightness of the image. The value is the maximum brightness.
The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterOpacity;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *maximumRasterBrightness;
/**
- Rotates hues around the color wheel.
-
- This property is measured in degrees.
+ Increase or reduce the brightness of the image. The value is the minimum brightness.
The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterHueRotate;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *minimumRasterBrightness;
/**
- Increase or reduce the brightness of the image. The value is the minimum brightness.
+ Increase or reduce the contrast of the image.
The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterBrightnessMin;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterContrast;
/**
- Increase or reduce the brightness of the image. The value is the maximum brightness.
+ Fade duration when a new tile is added.
+
+ This property is measured in milliseconds.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `300`. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterBrightnessMax;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterFadeDuration;
/**
- Increase or reduce the saturation of the image.
+ Rotates hues around the color wheel.
+
+ This property is measured in degrees.
The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterSaturation;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterHueRotate;
/**
- Increase or reduce the contrast of the image.
+ The opacity at which the image will be drawn.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterContrast;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterOpacity;
/**
- Fade duration when a new tile is added.
-
- This property is measured in milliseconds.
+ Increase or reduce the saturation of the image.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `300`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterFadeDuration;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *rasterSaturation;
@end
diff --git a/platform/darwin/src/MGLRasterStyleLayer.mm b/platform/darwin/src/MGLRasterStyleLayer.mm
index f616e89518..3b2c3bd83b 100644
--- a/platform/darwin/src/MGLRasterStyleLayer.mm
+++ b/platform/darwin/src/MGLRasterStyleLayer.mm
@@ -2,6 +2,7 @@
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
#import "MGLSource.h"
+#import "MGLMapView_Private.h"
#import "NSPredicate+MGLAdditions.h"
#import "MGLStyleLayer_Private.h"
#import "MGLStyleValue_Private.h"
@@ -11,90 +12,167 @@
@interface MGLRasterStyleLayer ()
-@property (nonatomic) mbgl::style::RasterLayer *layer;
+@property (nonatomic) mbgl::style::RasterLayer *rawLayer;
@end
@implementation MGLRasterStyleLayer
+{
+ std::unique_ptr<mbgl::style::RasterLayer> _pendingLayer;
+}
- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source
{
if (self = [super initWithIdentifier:identifier source:source]) {
- _layer = new mbgl::style::RasterLayer(identifier.UTF8String, source.identifier.UTF8String);
+ auto layer = std::make_unique<mbgl::style::RasterLayer>(identifier.UTF8String, source.identifier.UTF8String);
+ _pendingLayer = std::move(layer);
+ _rawLayer = _pendingLayer.get();
}
return self;
}
+#pragma mark - Adding to and removing from a map view
+
+- (void)addToMapView:(MGLMapView *)mapView
+{
+ if (_pendingLayer == nullptr) {
+ [NSException raise:@"MGLRedundantLayerException"
+ format:@"This instance %@ was already added to %@. Adding the same layer instance " \
+ "to the style more than once is invalid.", self, mapView.style];
+ }
+
+ [self addToMapView:mapView belowLayer:nil];
+}
+
+- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
+{
+ if (otherLayer) {
+ const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String};
+ mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId);
+ } else {
+ mapView.mbglMap->addLayer(std::move(_pendingLayer));
+ }
+}
+
+- (void)removeFromMapView:(MGLMapView *)mapView
+{
+ _pendingLayer = nullptr;
+ _rawLayer = nullptr;
+
+ auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String);
+ if (!removedLayer) {
+ return;
+ }
+
+ mbgl::style::RasterLayer *layer = dynamic_cast<mbgl::style::RasterLayer *>(removedLayer.get());
+ if (!layer) {
+ return;
+ }
+
+ removedLayer.release();
+
+ _pendingLayer = std::unique_ptr<mbgl::style::RasterLayer>(layer);
+ _rawLayer = _pendingLayer.get();
+}
#pragma mark - Accessing the Paint Attributes
-- (void)setRasterOpacity:(MGLStyleValue<NSNumber *> *)rasterOpacity {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterOpacity);
- self.layer->setRasterOpacity(mbglValue);
+- (void)setMaximumRasterBrightness:(MGLStyleValue<NSNumber *> *)maximumRasterBrightness {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(maximumRasterBrightness);
+ _rawLayer->setRasterBrightnessMax(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)rasterOpacity {
- auto propertyValue = self.layer->getRasterOpacity() ?: self.layer->getDefaultRasterOpacity();
+- (MGLStyleValue<NSNumber *> *)maximumRasterBrightness {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getRasterBrightnessMax() ?: _rawLayer->getDefaultRasterBrightnessMax();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setRasterHueRotate:(MGLStyleValue<NSNumber *> *)rasterHueRotate {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterHueRotate);
- self.layer->setRasterHueRotate(mbglValue);
+- (void)setMinimumRasterBrightness:(MGLStyleValue<NSNumber *> *)minimumRasterBrightness {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(minimumRasterBrightness);
+ _rawLayer->setRasterBrightnessMin(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)rasterHueRotate {
- auto propertyValue = self.layer->getRasterHueRotate() ?: self.layer->getDefaultRasterHueRotate();
+- (MGLStyleValue<NSNumber *> *)minimumRasterBrightness {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getRasterBrightnessMin() ?: _rawLayer->getDefaultRasterBrightnessMin();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setRasterBrightnessMin:(MGLStyleValue<NSNumber *> *)rasterBrightnessMin {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterBrightnessMin);
- self.layer->setRasterBrightnessMin(mbglValue);
+- (void)setRasterContrast:(MGLStyleValue<NSNumber *> *)rasterContrast {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterContrast);
+ _rawLayer->setRasterContrast(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)rasterBrightnessMin {
- auto propertyValue = self.layer->getRasterBrightnessMin() ?: self.layer->getDefaultRasterBrightnessMin();
+- (MGLStyleValue<NSNumber *> *)rasterContrast {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getRasterContrast() ?: _rawLayer->getDefaultRasterContrast();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setRasterBrightnessMax:(MGLStyleValue<NSNumber *> *)rasterBrightnessMax {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterBrightnessMax);
- self.layer->setRasterBrightnessMax(mbglValue);
+- (void)setRasterFadeDuration:(MGLStyleValue<NSNumber *> *)rasterFadeDuration {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterFadeDuration);
+ _rawLayer->setRasterFadeDuration(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)rasterBrightnessMax {
- auto propertyValue = self.layer->getRasterBrightnessMax() ?: self.layer->getDefaultRasterBrightnessMax();
+- (MGLStyleValue<NSNumber *> *)rasterFadeDuration {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getRasterFadeDuration() ?: _rawLayer->getDefaultRasterFadeDuration();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setRasterSaturation:(MGLStyleValue<NSNumber *> *)rasterSaturation {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterSaturation);
- self.layer->setRasterSaturation(mbglValue);
+- (void)setRasterHueRotate:(MGLStyleValue<NSNumber *> *)rasterHueRotate {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterHueRotate);
+ _rawLayer->setRasterHueRotate(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)rasterSaturation {
- auto propertyValue = self.layer->getRasterSaturation() ?: self.layer->getDefaultRasterSaturation();
+- (MGLStyleValue<NSNumber *> *)rasterHueRotate {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getRasterHueRotate() ?: _rawLayer->getDefaultRasterHueRotate();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setRasterContrast:(MGLStyleValue<NSNumber *> *)rasterContrast {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterContrast);
- self.layer->setRasterContrast(mbglValue);
+- (void)setRasterOpacity:(MGLStyleValue<NSNumber *> *)rasterOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterOpacity);
+ _rawLayer->setRasterOpacity(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)rasterContrast {
- auto propertyValue = self.layer->getRasterContrast() ?: self.layer->getDefaultRasterContrast();
+- (MGLStyleValue<NSNumber *> *)rasterOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getRasterOpacity() ?: _rawLayer->getDefaultRasterOpacity();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setRasterFadeDuration:(MGLStyleValue<NSNumber *> *)rasterFadeDuration {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterFadeDuration);
- self.layer->setRasterFadeDuration(mbglValue);
+- (void)setRasterSaturation:(MGLStyleValue<NSNumber *> *)rasterSaturation {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(rasterSaturation);
+ _rawLayer->setRasterSaturation(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)rasterFadeDuration {
- auto propertyValue = self.layer->getRasterFadeDuration() ?: self.layer->getDefaultRasterFadeDuration();
+- (MGLStyleValue<NSNumber *> *)rasterSaturation {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getRasterSaturation() ?: _rawLayer->getDefaultRasterSaturation();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
+
@end
diff --git a/platform/darwin/src/MGLRuntimeStylingTests.m.ejs b/platform/darwin/src/MGLRuntimeStylingTests.m.ejs
index c1492167b4..720ee4547e 100644
--- a/platform/darwin/src/MGLRuntimeStylingTests.m.ejs
+++ b/platform/darwin/src/MGLRuntimeStylingTests.m.ejs
@@ -6,9 +6,9 @@
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
-#import "MGLMapViewTests.h"
+#import "MGLStyleLayerTests.h"
-@interface MGL<%- camelize(type) %>LayerTests : MGLMapViewTests
+@interface MGL<%- camelize(type) %>LayerTests : MGLStyleLayerTests
@end
@implementation MGL<%- camelize(type) %>LayerTests
diff --git a/platform/darwin/src/MGLSource.mm b/platform/darwin/src/MGLSource.mm
index 1b889d44d7..2fa580df89 100644
--- a/platform/darwin/src/MGLSource.mm
+++ b/platform/darwin/src/MGLSource.mm
@@ -2,6 +2,14 @@
#include <mbgl/style/source.hpp>
+@interface MGLSource ()
+
+// Even though this class is abstract, MGLStyle uses it to represent some
+// special internal source types like mbgl::AnnotationSource.
+@property (nonatomic) mbgl::style::Source *rawSource;
+
+@end
+
@implementation MGLSource
- (instancetype)initWithIdentifier:(NSString *)identifier
@@ -12,4 +20,23 @@
return self;
}
+- (void)addToMapView:(MGLMapView *)mapView {
+ [NSException raise:NSInvalidArgumentException format:
+ @"The source %@ cannot be added to the style. "
+ @"Make sure the source was created as a member of a concrete subclass of MGLSource.",
+ self];
+}
+
+- (void)removeFromMapView:(MGLMapView *)mapView {
+ [NSException raise:NSInvalidArgumentException format:
+ @"The source %@ cannot be removed from the style. "
+ @"Make sure the source was created as a member of a concrete subclass of MGLSource.",
+ self];
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@: %p; identifier = %@>",
+ NSStringFromClass([self class]), (void *)self, self.identifier];
+}
+
@end
diff --git a/platform/darwin/src/MGLSource_Private.h b/platform/darwin/src/MGLSource_Private.h
index 954dd5ae38..5f63f1fb1d 100644
--- a/platform/darwin/src/MGLSource_Private.h
+++ b/platform/darwin/src/MGLSource_Private.h
@@ -27,4 +27,13 @@
*/
- (void)addToMapView:(MGLMapView *)mapView;
+/**
+ Removes the mbgl source that this object represents from the mbgl map.
+
+ When a mbgl source is removed, ownership of the object is transferred back
+ to the `MGLSource` instance and the unique_ptr reference is valid again. It is
+ safe to add the source back to the style after it is removed.
+ */
+- (void)removeFromMapView:(MGLMapView *)mapView;
+
@end
diff --git a/platform/darwin/src/MGLStyle.h b/platform/darwin/src/MGLStyle.h
index 7f01c230c5..54ca267bab 100644
--- a/platform/darwin/src/MGLStyle.h
+++ b/platform/darwin/src/MGLStyle.h
@@ -37,7 +37,7 @@ static const NSInteger MGLStyleDefaultVersion = 9;
*/
@interface MGLStyle : NSObject
-#pragma mark Default Style URLs
+#pragma mark Accessing Common Styles
/**
Returns the URL to version 8 of the
@@ -165,6 +165,8 @@ static const NSInteger MGLStyleDefaultVersion = 9;
*/
+ (NSURL *)satelliteStreetsStyleURLWithVersion:(NSInteger)version;
+#pragma mark Accessing Metadata About the Style
+
/**
The name of the style.
@@ -172,63 +174,164 @@ static const NSInteger MGLStyleDefaultVersion = 9;
*/
@property (readonly, copy, nullable) NSString *name;
-#pragma mark Runtime Styling
+#pragma mark Managing Sources
/**
- Returns a layer that conforms to `MGLStyleLayer` if any layer with the given
- identifier was found.
-
- @return An instance of a concrete subclass of `MGLStyleLayer` associated with
- the given identifier.
+ A set containing the style’s sources.
*/
-- (nullable MGLStyleLayer *)layerWithIdentifier:(NSString *)identifier;
-
+@property (nonatomic, strong) NS_MUTABLE_SET_OF(MGLSource *) *sources;
/**
- Returns a source if any source with the given identifier was found.
+ Returns a source with the given identifier in the current style.
+
+ @note Source identifiers are not guaranteed to exist across styles or different
+ versions of the same style. Applications that use this API must first set the
+ 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 source identifer name changes that will occur in the default
+ style’s sources over time.
@return An instance of a concrete subclass of `MGLSource` associated with the
- given identifier.
+ given identifier, or `nil` if the current style contains no such source.
*/
- (nullable MGLSource *)sourceWithIdentifier:(NSString *)identifier;
/**
+ Adds a new source to the current style.
+
+ @note Adding the same source instance more than once will result in a
+ `MGLRedundantSourceException`. Reusing the same source identifier, even with
+ different source instances, will result in a
+ `MGLRedundantSourceIdentiferException`.
+
+ @param source The source to add to the current style.
+ */
+- (void)addSource:(MGLSource *)source;
+
+/**
+ Removes a source from the current style.
+
+ @note Source identifiers are not guaranteed to exist across styles or different
+ versions of the same style. Applications that use this API must first set the
+ 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 source identifer name changes that will occur in the default
+ style’s sources over time.
+
+ @param source The source to remove from the current style.
+ */
+- (void)removeSource:(MGLSource *)source;
+
+#pragma mark Managing Style Layers
+
+/**
+ The layers included in the style, arranged according to their front-to-back
+ ordering on the screen.
+ */
+@property (nonatomic, strong) NS_MUTABLE_ARRAY_OF(MGLStyleLayer *) *layers;
+
+/**
+ Returns a style layer with the given identifier in the current style.
+
+ @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
+ the 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.
+
+ @return An instance of a concrete subclass of `MGLStyleLayer` associated with
+ the given identifier, or `nil` if the current style contains no such style
+ layer.
+ */
+- (nullable MGLStyleLayer *)layerWithIdentifier:(NSString *)identifier;
+
+/**
Adds a new layer on top of existing layers.
+ @note Adding the same layer instance more than once will result in a
+ `MGLRedundantLayerException`. Reusing the same layer identifer, even with
+ different layer instances, will also result in an exception.
+
@param layer The layer object to add to the map view. This object must be an
instance of a concrete subclass of `MGLStyleLayer`.
*/
- (void)addLayer:(MGLStyleLayer *)layer;
/**
+ Inserts a new layer into the style at the given index.
+
+ @note Adding the same layer instance more than once will result in a
+ `MGLRedundantLayerException`. Reusing the same layer identifer, even with
+ different layer instances, will also result in an exception.
+
+ @param layer The layer to insert.
+ @param index The index at which to insert the layer. An index of 0 would send
+ the layer to the back; an index equal to the number of objects in the
+ `layers` property would bring the layer to the front.
+ */
+- (void)insertLayer:(MGLStyleLayer *)layer atIndex:(NSUInteger)index;
+
+/**
Inserts a new layer below another layer.
+
+ @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
+ the 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.
+
+ Inserting the same layer instance more than once will result in a
+ `MGLRedundantLayerException`. Reusing the same layer identifer, even with
+ different layer instances, will also result in an exception.
+
+ @param layer The layer to insert.
+ @param sibling An existing layer in the style.
+ */
+- (void)insertLayer:(MGLStyleLayer *)layer belowLayer:(MGLStyleLayer *)sibling;
- @param layer Layer to be inserted.
- @param belowLayer A layer that's already on the map view.
+/**
+ Inserts a new layer above another layer.
+
+ @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
+ the 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.
+
+ Inserting the same layer instance more than once will result in a
+ `MGLRedundantLayerException`. Reusing the same layer identifer, even with
+ different layer instances, will also result in an exception.
+
+ @param layer The layer to insert.
+ @param sibling An existing layer in the style.
*/
-- (void)insertLayer:(MGLStyleLayer *)layer belowLayer:(MGLStyleLayer *)otherLayer;
+- (void)insertLayer:(MGLStyleLayer *)layer aboveLayer:(MGLStyleLayer *)sibling;
/**
Removes a layer from the map view.
+
+ @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
+ the 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.
@param layer The layer object to remove from the map view. This object
must conform to the `MGLStyleLayer` protocol.
*/
- (void)removeLayer:(MGLStyleLayer *)layer;
-/**
- Adds a new source to the map view.
-
- @param source The source to add to the map view.
- */
-- (void)addSource:(MGLSource *)source;
-
-/**
- Removes a source from the map view.
-
- @param source The source to remove.
- */
-- (void)removeSource:(MGLSource *)source;
+#pragma mark Managing Style Classes
/**
Currently active style classes, represented as an array of string identifiers.
@@ -253,17 +356,27 @@ static const NSInteger MGLStyleDefaultVersion = 9;
/**
Deactivates the style class with the given identifier.
+
+ @note Style class names are not guaranteed to exist across styles or different
+ versions of the same style. Applications that use this API must first set the
+ 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 style class name changes that will occur in the default
+ style over time.
@param styleClass The style class to deactivate.
*/
- (void)removeStyleClass:(NSString *)styleClass;
-/**
-Adds or overrides an image used by the style’s layers.
-
-To use an image in a style layer, give it a unique name using this method,
-then set the `iconImage` property of an `MGLSymbolStyleLayer` object to that name.
+#pragma mark Managing a Style’s Images
+/**
+ Adds or overrides an image used by the style’s layers.
+
+ To use an image in a style layer, give it a unique name using this method, then
+ set the `iconImage` property of an `MGLSymbolStyleLayer` object to that name.
+
@param image The image for the name.
@param name The name of the image to set to the style.
*/
@@ -271,6 +384,14 @@ then set the `iconImage` property of an `MGLSymbolStyleLayer` object to that nam
/**
Removes a name and its associated image from the style.
+
+ @note Names and their associated images are not guaranteed to exist across
+ styles or different versions of the same style. Applications that use this
+ API must first set the 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 image name changes that will
+ occur in the default style over time.
@param name The name of the image to remove.
*/
diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm
index 6da3cae3df..6116f4df28 100644
--- a/platform/darwin/src/MGLStyle.mm
+++ b/platform/darwin/src/MGLStyle.mm
@@ -39,12 +39,16 @@
#endif
@interface MGLStyle()
-@property (nonatomic, weak) MGLMapView *mapView;
+
+@property (nonatomic, readwrite, weak) MGLMapView *mapView;
@property (readonly, copy, nullable) NSURL *URL;
+
@end
@implementation MGLStyle
+#pragma mark Default style URLs
+
static_assert(mbgl::util::default_styles::currentVersion == MGLStyleDefaultVersion, "mbgl::util::default_styles::currentVersion and MGLStyleDefaultVersion disagree.");
/// @param name The style’s marketing name, written in lower camelCase.
@@ -99,21 +103,197 @@ static NSURL *MGLStyleURL_emerald;
return MGLStyleURL_emerald;
}
-- (NSString *)name {
- return @(self.mapView.mbglMap->getStyleName().c_str());
+#pragma mark -
+
+- (instancetype)initWithMapView:(MGLMapView *)mapView {
+ if (self = [super init]) {
+ _mapView = mapView;
+ }
+ return self;
}
- (NSURL *)URL {
return [NSURL URLWithString:@(self.mapView.mbglMap->getStyleURL().c_str())];
}
-- (MGLStyleLayer *)layerWithIdentifier:(NSString *)identifier
+- (NSString *)name {
+ std::string name = self.mapView.mbglMap->getStyleName();
+ return name.empty() ? nil : @(name.c_str());
+}
+
+#pragma mark Sources
+
+- (NS_MUTABLE_SET_OF(MGLSource *) *)sources {
+ auto rawSources = self.mapView.mbglMap->getSources();
+ NSMutableSet *sources = [NSMutableSet setWithCapacity:rawSources.size()];
+ for (auto rawSource = rawSources.begin(); rawSource != rawSources.end(); ++rawSource) {
+ MGLSource *source = [self sourceFromMBGLSource:*rawSource];
+ [sources addObject:source];
+ }
+ return sources;
+}
+
+- (void)setSources:(NS_MUTABLE_SET_OF(MGLSource *) *)sources {
+ for (MGLSource *source in self.sources) {
+ [self removeSource:source];
+ }
+ for (MGLSource *source in sources) {
+ [self addSource:source];
+ }
+}
+
+- (NSUInteger)countOfSources {
+ auto rawSources = self.mapView.mbglMap->getSources();
+ return rawSources.size();
+}
+
+- (MGLSource *)memberOfSources:(MGLSource *)object {
+ return [self sourceWithIdentifier:object.identifier];
+}
+
+- (MGLSource *)sourceWithIdentifier:(NSString *)identifier
{
- auto mbglLayer = self.mapView.mbglMap->getLayer(identifier.UTF8String);
- if (!mbglLayer) {
+ auto rawSource = self.mapView.mbglMap->getSource(identifier.UTF8String);
+ return rawSource ? [self sourceFromMBGLSource:rawSource] : nil;
+}
+
+- (MGLSource *)sourceFromMBGLSource:(mbgl::style::Source *)mbglSource {
+ NSString *identifier = @(mbglSource->getID().c_str());
+
+ // TODO: Fill in options specific to the respective source classes
+ // https://github.com/mapbox/mapbox-gl-native/issues/6584
+ MGLSource *source;
+ if (mbglSource->is<mbgl::style::VectorSource>()) {
+ source = [[MGLVectorSource alloc] initWithIdentifier:identifier];
+ } else if (mbglSource->is<mbgl::style::GeoJSONSource>()) {
+ source = [[MGLGeoJSONSource alloc] initWithIdentifier:identifier];
+ } else if (mbglSource->is<mbgl::style::RasterSource>()) {
+ source = [[MGLRasterSource alloc] initWithIdentifier:identifier];
+ } else {
+ source = [[MGLSource alloc] initWithIdentifier:identifier];
+ }
+
+ source.rawSource = mbglSource;
+
+ return source;
+}
+
+- (void)addSource:(MGLSource *)source
+{
+ if (!source.rawSource) {
+ [NSException raise:NSInvalidArgumentException format:
+ @"The source %@ cannot be added to the style. "
+ @"Make sure the source was created as a member of a concrete subclass of MGLSource.",
+ source];
+ }
+
+ try {
+ [source addToMapView:self.mapView];
+ } catch (std::runtime_error & err) {
+ [NSException raise:@"MGLRedundantSourceIdentiferException" format:@"%s", err.what()];
+ }
+}
+
+- (void)removeSource:(MGLSource *)source
+{
+ if (!source.rawSource) {
+ [NSException raise:NSInvalidArgumentException format:
+ @"The source %@ cannot be removed from the style. "
+ @"Make sure the source was created as a member of a concrete subclass of MGLSource.",
+ source];
+ }
+ [source removeFromMapView:self.mapView];
+}
+
+#pragma mark Style layers
+
+- (NS_MUTABLE_ARRAY_OF(MGLStyleLayer *) *)layers
+{
+ auto layers = self.mapView.mbglMap->getLayers();
+ NSMutableArray *styleLayers = [NSMutableArray arrayWithCapacity:layers.size()];
+ for (auto layer = layers.rbegin(); layer != layers.rend(); ++layer) {
+ MGLStyleLayer *styleLayer = [self layerFromMBGLLayer:*layer];
+ [styleLayers addObject:styleLayer];
+ }
+ return styleLayers;
+}
+
+- (void)setLayers:(NS_MUTABLE_ARRAY_OF(MGLStyleLayer *) *)layers {
+ for (MGLStyleLayer *layer in self.layers.reverseObjectEnumerator) {
+ [self removeLayer:layer];
+ }
+ for (MGLStyleLayer *layer in layers.reverseObjectEnumerator) {
+ [self addLayer:layer];
+ }
+}
+
+- (NSUInteger)countOfLayers
+{
+ return self.mapView.mbglMap->getLayers().size();
+}
+
+- (MGLStyleLayer *)objectInLayersAtIndex:(NSUInteger)index
+{
+ auto layers = self.mapView.mbglMap->getLayers();
+ if (index > layers.size() - 1) {
+ [NSException raise:NSRangeException
+ format:@"No style layer at index %lu.", (unsigned long)index];
return nil;
}
+ auto layer = layers.at(layers.size() - 1 - index);
+ return [self layerFromMBGLLayer:layer];
+}
+- (void)getLayers:(MGLStyleLayer **)buffer range:(NSRange)inRange
+{
+ auto layers = self.mapView.mbglMap->getLayers();
+ if (NSMaxRange(inRange) > layers.size()) {
+ [NSException raise:NSRangeException
+ format:@"Style layer range %@ is out of bounds.", NSStringFromRange(inRange)];
+ }
+ NSUInteger i = 0;
+ for (auto layer = *(layers.rbegin() + inRange.location); i < inRange.length; ++layer, ++i) {
+ MGLStyleLayer *styleLayer = [self layerFromMBGLLayer:layer];
+ buffer[i] = styleLayer;
+ }
+}
+
+- (void)insertObject:(MGLStyleLayer *)styleLayer inLayersAtIndex:(NSUInteger)index
+{
+ if (!styleLayer.rawLayer) {
+ [NSException raise:NSInvalidArgumentException format:
+ @"The style layer %@ cannot be inserted into the style. "
+ @"Make sure the style layer was created as a member of a concrete subclass of MGLStyleLayer.",
+ styleLayer];
+ }
+ auto layers = self.mapView.mbglMap->getLayers();
+ if (index > layers.size()) {
+ [NSException raise:NSRangeException
+ format:@"Cannot insert style layer at out-of-bounds index %lu.", (unsigned long)index];
+ } else if (index == 0) {
+ [styleLayer addToMapView:self.mapView];
+ } else {
+ MGLStyleLayer *sibling = [self layerFromMBGLLayer:layers.at(layers.size() - index)];
+ [styleLayer addToMapView:self.mapView belowLayer:sibling];
+ }
+}
+
+- (void)removeObjectFromLayersAtIndex:(NSUInteger)index
+{
+ auto layers = self.mapView.mbglMap->getLayers();
+ if (index > layers.size() - 1) {
+ [NSException raise:NSRangeException
+ format:@"Cannot remove style layer at out-of-bounds index %lu.", (unsigned long)index];
+ }
+ auto layer = layers.at(layers.size() - 1 - index);
+ self.mapView.mbglMap->removeLayer(layer->getID());
+}
+
+- (MGLStyleLayer *)layerFromMBGLLayer:(mbgl::style::Layer *)mbglLayer
+{
+ NSParameterAssert(mbglLayer);
+
+ NSString *identifier = @(mbglLayer->getID().c_str());
MGLStyleLayer *styleLayer;
if (auto fillLayer = mbglLayer->as<mbgl::style::FillLayer>()) {
MGLSource *source = [self sourceWithIdentifier:@(fillLayer->getSourceID().c_str())];
@@ -137,116 +317,112 @@ static NSURL *MGLStyleURL_emerald;
return nil;
}
- styleLayer.layer = mbglLayer;
+ styleLayer.rawLayer = mbglLayer;
return styleLayer;
}
-- (MGLSource *)sourceWithIdentifier:(NSString *)identifier
+- (MGLStyleLayer *)layerWithIdentifier:(NSString *)identifier
{
- auto mbglSource = self.mapView.mbglMap->getSource(identifier.UTF8String);
-
- if (!mbglSource) {
- return nil;
- }
-
- // TODO: Fill in options specific to the respective source classes
- // https://github.com/mapbox/mapbox-gl-native/issues/6584
- MGLSource *source;
- if (mbglSource->is<mbgl::style::VectorSource>()) {
- source = [[MGLVectorSource alloc] initWithIdentifier:identifier];
- } else if (mbglSource->is<mbgl::style::GeoJSONSource>()) {
- source = [[MGLGeoJSONSource alloc] initWithIdentifier:identifier];
- } else if (mbglSource->is<mbgl::style::RasterSource>()) {
- source = [[MGLRasterSource alloc] initWithIdentifier:identifier];
- } else {
- NSAssert(NO, @"Unrecognized source type");
- return nil;
- }
-
- source.rawSource = mbglSource;
-
- return source;
+ auto mbglLayer = self.mapView.mbglMap->getLayer(identifier.UTF8String);
+ return mbglLayer ? [self layerFromMBGLLayer:mbglLayer] : nil;
}
- (void)removeLayer:(MGLStyleLayer *)layer
{
- if (!layer.layer) {
+ if (!layer.rawLayer) {
[NSException raise:NSInvalidArgumentException format:
@"The style layer %@ cannot be removed from the style. "
@"Make sure the style layer was created as a member of a concrete subclass of MGLStyleLayer.",
layer];
}
-
- self.mapView.mbglMap->removeLayer(layer.identifier.UTF8String);
+ [self willChangeValueForKey:@"layers"];
+ [layer removeFromMapView:self.mapView];
+ [self didChangeValueForKey:@"layers"];
}
- (void)addLayer:(MGLStyleLayer *)layer
{
- if (!layer.layer) {
+ if (!layer.rawLayer) {
[NSException raise:NSInvalidArgumentException format:
@"The style layer %@ cannot be added to the style. "
@"Make sure the style layer was created as a member of a concrete subclass of MGLStyleLayer.",
layer];
}
+ [self willChangeValueForKey:@"layers"];
+ [layer addToMapView:self.mapView];
+ [self didChangeValueForKey:@"layers"];
+}
- self.mapView.mbglMap->addLayer(std::unique_ptr<mbgl::style::Layer>(layer.layer));
+- (void)insertLayer:(MGLStyleLayer *)layer atIndex:(NSUInteger)index {
+ [self insertObject:layer inLayersAtIndex:index];
}
-- (void)insertLayer:(MGLStyleLayer *)layer belowLayer:(MGLStyleLayer *)otherLayer
+- (void)insertLayer:(MGLStyleLayer *)layer belowLayer:(MGLStyleLayer *)sibling
{
- if (!layer.layer) {
+ if (!layer.rawLayer) {
[NSException raise:NSInvalidArgumentException
format:
@"The style layer %@ cannot be added to the style. "
@"Make sure the style layer was created as a member of a concrete subclass of MGLStyleLayer.",
layer];
}
- if (!otherLayer.layer) {
+ if (!sibling.rawLayer) {
[NSException raise:NSInvalidArgumentException
format:
- @"A style layer cannot be placed before %@ in the style. "
- @"Make sure otherLayer was obtained using -[MGLStyle layerWithIdentifier:].",
- otherLayer];
+ @"A style layer cannot be placed below %@ in the style. "
+ @"Make sure sibling was obtained using -[MGLStyle layerWithIdentifier:].",
+ sibling];
}
-
- const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String};
- self.mapView.mbglMap->addLayer(std::unique_ptr<mbgl::style::Layer>(layer.layer), belowLayerId);
+ [self willChangeValueForKey:@"layers"];
+ [layer addToMapView:self.mapView belowLayer:sibling];
+ [self didChangeValueForKey:@"layers"];
}
-- (void)addSource:(MGLSource *)source
-{
- if (!source.rawSource) {
- [NSException raise:NSInvalidArgumentException format:
- @"The source %@ cannot be added to the style. "
- @"Make sure the source was created as a member of a concrete subclass of MGLSource.",
- source];
+- (void)insertLayer:(MGLStyleLayer *)layer aboveLayer:(MGLStyleLayer *)sibling {
+ if (!layer.rawLayer) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"The style layer %@ cannot be added to the style. "
+ @"Make sure the style layer was created as a member of a concrete subclass of MGLStyleLayer.",
+ layer];
}
-
- try {
- [source addToMapView:self.mapView];
- } catch (std::runtime_error & err) {
- [NSException raise:@"Could not add source" format:@"%s", err.what()];
+ if (!sibling.rawLayer) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"A style layer cannot be placed above %@ in the style. "
+ @"Make sure sibling was obtained using -[MGLStyle layerWithIdentifier:].",
+ sibling];
}
-}
-
-- (void)removeSource:(MGLSource *)source
-{
- if (!source.rawSource) {
- [NSException raise:NSInvalidArgumentException format:
- @"The source %@ cannot be removed from the style. "
- @"Make sure the source was created as a member of a concrete subclass of MGLSource.",
- source];
+
+ auto layers = self.mapView.mbglMap->getLayers();
+ std::string siblingIdentifier = sibling.identifier.UTF8String;
+ NSUInteger index = 0;
+ for (auto layer : layers) {
+ if (layer->getID() == siblingIdentifier) {
+ break;
+ }
+ index++;
}
-
- self.mapView.mbglMap->removeSource(source.identifier.UTF8String);
- // Once a mbgl source is removed from the map, ownership does not return
- // to the MGL source. Therefore, the rawSource pointer is set to NULL
- // so that the implementation of MGL source can avoid using it again.
- source.rawSource = NULL;
+ [self willChangeValueForKey:@"layers"];
+ if (index + 1 > layers.size()) {
+ [NSException raise:NSInvalidArgumentException
+ format:
+ @"A style layer cannot be placed above %@ in the style. "
+ @"Make sure sibling was obtained using -[MGLStyle layerWithIdentifier:].",
+ sibling];
+ } else if (index + 1 == layers.size()) {
+ [layer addToMapView:self.mapView];
+ } else {
+ MGLStyleLayer *sibling = [self layerFromMBGLLayer:layers.at(index + 1)];
+ [layer addToMapView:self.mapView belowLayer:sibling];
+ }
+ [self didChangeValueForKey:@"layers"];
}
+#pragma mark Style classes
+
- (NS_ARRAY_OF(NSString *) *)styleClasses
{
const std::vector<std::string> &appliedClasses = self.mapView.mbglMap->getClasses();
@@ -279,6 +455,11 @@ static NSURL *MGLStyleURL_emerald;
self.mapView.mbglMap->setClasses(newAppliedClasses);
}
+- (NSUInteger)countOfStyleClasses {
+ const auto &classes = self.mapView.mbglMap->getClasses();
+ return classes.size();
+}
+
- (BOOL)hasStyleClass:(NSString *)styleClass
{
return styleClass && self.mapView.mbglMap->hasClass([styleClass UTF8String]);
@@ -300,6 +481,8 @@ static NSURL *MGLStyleURL_emerald;
}
}
+#pragma mark Style images
+
- (void)setImage:(MGLImage *)image forName:(NSString *)name
{
NSAssert(image, @"image is null");
diff --git a/platform/darwin/src/MGLStyleLayer.mm b/platform/darwin/src/MGLStyleLayer.mm
index 293aa54f30..6d9dabf25e 100644
--- a/platform/darwin/src/MGLStyleLayer.mm
+++ b/platform/darwin/src/MGLStyleLayer.mm
@@ -3,12 +3,6 @@
#include <mbgl/style/layer.hpp>
-@interface MGLStyleLayer ()
-
-@property (nonatomic) mbgl::style::Layer *layer;
-
-@end
-
@implementation MGLStyleLayer
- (instancetype)initWithIdentifier:(NSString *)identifier
@@ -21,36 +15,55 @@
- (void)setVisible:(BOOL)visible
{
+ MGLAssertStyleLayerIsValid();
+
mbgl::style::VisibilityType v = visible
? mbgl::style::VisibilityType::Visible
: mbgl::style::VisibilityType::None;
- self.layer->setVisibility(v);
+ self.rawLayer->setVisibility(v);
}
- (BOOL)isVisible
{
- mbgl::style::VisibilityType v = self.layer->getVisibility();
+ MGLAssertStyleLayerIsValid();
+
+ mbgl::style::VisibilityType v = self.rawLayer->getVisibility();
return (v == mbgl::style::VisibilityType::Visible);
}
- (void)setMaximumZoomLevel:(float)maximumZoomLevel
{
- self.layer->setMaxZoom(maximumZoomLevel);
+ MGLAssertStyleLayerIsValid();
+
+ self.rawLayer->setMaxZoom(maximumZoomLevel);
}
- (float)maximumZoomLevel
{
- return self.layer->getMaxZoom();
+ MGLAssertStyleLayerIsValid();
+
+ return self.rawLayer->getMaxZoom();
}
- (void)setMinimumZoomLevel:(float)minimumZoomLevel
{
- self.layer->setMinZoom(minimumZoomLevel);
+ MGLAssertStyleLayerIsValid();
+
+ self.rawLayer->setMinZoom(minimumZoomLevel);
}
- (float)minimumZoomLevel
{
- return self.layer->getMinZoom();
+ MGLAssertStyleLayerIsValid();
+
+ return self.rawLayer->getMinZoom();
+}
+
+- (NSString *)description
+{
+ return [NSString stringWithFormat:@"<%@: %p; identifier = %@; visible = %@>",
+ NSStringFromClass([self class]), (void *)self, self.identifier,
+ self.visible ? @"YES" : @"NO"];
}
@end
diff --git a/platform/darwin/src/MGLStyleLayer.mm.ejs b/platform/darwin/src/MGLStyleLayer.mm.ejs
index 3678e9ec52..c89912c1ff 100644
--- a/platform/darwin/src/MGLStyleLayer.mm.ejs
+++ b/platform/darwin/src/MGLStyleLayer.mm.ejs
@@ -2,79 +2,181 @@
const type = locals.type;
const layoutProperties = locals.layoutProperties;
const paintProperties = locals.paintProperties;
+ const containsEnumerationProperties = locals.containsEnumerationProperties;
-%>
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
#import "MGLSource.h"
+#import "MGLMapView_Private.h"
#import "NSPredicate+MGLAdditions.h"
#import "MGLStyleLayer_Private.h"
#import "MGLStyleValue_Private.h"
#import "MGL<%- camelize(type) %>StyleLayer.h"
#include <mbgl/style/layers/<%- type %>_layer.hpp>
+<% if (containsEnumerationProperties) { -%>
+namespace mbgl {
+
+<% if (layoutProperties.length) { -%>
+<% for (const property of layoutProperties) { -%>
+<% if (property.type == "enum") { -%>
+ MBGL_DEFINE_ENUM(MGL<%- camelize(originalPropertyName(property)) %>, {
+<% for (const value in property.values) { -%>
+ { MGL<%- camelize(originalPropertyName(property)) %><%- camelize(value) %>, "<%-value%>" },
+<% } -%>
+ });
+
+<% } -%>
+<% } -%>
+<% } -%>
+<% if (paintProperties.length) { -%>
+<% for (const property of paintProperties) { -%>
+<% if (property.type == "enum") { -%>
+ MBGL_DEFINE_ENUM(MGL<%- camelize(originalPropertyName(property)) %>, {
+<% for (const value in property.values) { -%>
+ { MGL<%- camelize(originalPropertyName(property)) %><%- camelize(value) %>, "<%-value%>" },
+<% } -%>
+ });
+
+<% } -%>
+<% } -%>
+<% } -%>
+}
+<% } -%>
@interface MGL<%- camelize(type) %>StyleLayer ()
-@property (nonatomic) mbgl::style::<%- camelize(type) %>Layer *layer;
+@property (nonatomic) mbgl::style::<%- camelize(type) %>Layer *rawLayer;
@end
@implementation MGL<%- camelize(type) %>StyleLayer
+{
+ std::unique_ptr<mbgl::style::<%- camelize(type) %>Layer> _pendingLayer;
+}
<% if (type == 'background') { -%>
- (instancetype)initWithIdentifier:(NSString *)identifier
{
if (self = [super initWithIdentifier:identifier]) {
- _layer = new mbgl::style::<%- camelize(type) %>Layer(identifier.UTF8String);
+ auto layer = std::make_unique<mbgl::style::<%- camelize(type) %>Layer>(identifier.UTF8String);
+ _pendingLayer = std::move(layer);
+ _rawLayer = _pendingLayer.get();
}
return self;
}
+
<% } else { -%>
- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source
{
if (self = [super initWithIdentifier:identifier source:source]) {
- _layer = new mbgl::style::<%- camelize(type) %>Layer(identifier.UTF8String, source.identifier.UTF8String);
+ auto layer = std::make_unique<mbgl::style::<%- camelize(type) %>Layer>(identifier.UTF8String, source.identifier.UTF8String);
+ _pendingLayer = std::move(layer);
+ _rawLayer = _pendingLayer.get();
}
return self;
}
<% } -%>
-
<% if (type !== 'background' && type !== 'raster') { -%>
- (NSString *)sourceLayerIdentifier
{
- auto layerID = self.layer->getSourceLayer();
+ MGLAssertStyleLayerIsValid();
+
+ auto layerID = _rawLayer->getSourceLayer();
return layerID.empty() ? nil : @(layerID.c_str());
}
- (void)setSourceLayerIdentifier:(NSString *)sourceLayerIdentifier
{
- self.layer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: "");
+ MGLAssertStyleLayerIsValid();
+
+ _rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: "");
}
- (void)setPredicate:(NSPredicate *)predicate
{
- self.layer->setFilter(predicate.mgl_filter);
+ MGLAssertStyleLayerIsValid();
+
+ _rawLayer->setFilter(predicate.mgl_filter);
}
- (NSPredicate *)predicate
{
- return [NSPredicate mgl_predicateWithFilter:self.layer->getFilter()];
-}
+ MGLAssertStyleLayerIsValid();
+ return [NSPredicate mgl_predicateWithFilter:_rawLayer->getFilter()];
+}
<% } -%>
+#pragma mark - Adding to and removing from a map view
+
+- (void)addToMapView:(MGLMapView *)mapView
+{
+ if (_pendingLayer == nullptr) {
+ [NSException raise:@"MGLRedundantLayerException"
+ format:@"This instance %@ was already added to %@. Adding the same layer instance " \
+ "to the style more than once is invalid.", self, mapView.style];
+ }
+
+ [self addToMapView:mapView belowLayer:nil];
+}
+
+- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
+{
+ if (otherLayer) {
+ const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String};
+ mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId);
+ } else {
+ mapView.mbglMap->addLayer(std::move(_pendingLayer));
+ }
+}
+
+- (void)removeFromMapView:(MGLMapView *)mapView
+{
+ _pendingLayer = nullptr;
+ _rawLayer = nullptr;
+
+ auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String);
+ if (!removedLayer) {
+ return;
+ }
+
+ mbgl::style::<%- camelize(type) %>Layer *layer = dynamic_cast<mbgl::style::<%- camelize(type) %>Layer *>(removedLayer.get());
+ if (!layer) {
+ return;
+ }
+
+ removedLayer.release();
+
+ _pendingLayer = std::unique_ptr<mbgl::style::<%- camelize(type) %>Layer>(layer);
+ _rawLayer = _pendingLayer.get();
+}
+
<% if (layoutProperties.length) { -%>
#pragma mark - Accessing the Layout Attributes
<% for (const property of layoutProperties) { -%>
- (void)set<%- camelize(property.name) %>:(MGLStyleValue<<%- propertyType(property, true) %>> *)<%- objCName(property) %> {
+ MGLAssertStyleLayerIsValid();
+
+<% if (property.type == "enum") { -%>
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::<%- mbglType(property) %>, NSValue *, mbgl::style::<%- mbglType(property) %>, MGL<%- camelize(originalPropertyName(property)) %>>().toEnumPropertyValue(<%- objCName(property) %>);
+ _rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue);
+<% } else { -%>
auto mbglValue = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toPropertyValue(<%- objCName(property) %>);
- self.layer->set<%- camelize(property.name) %>(mbglValue);
+ _rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue);
+<% } -%>
}
- (MGLStyleValue<<%- propertyType(property, true) %>> *)<%- objCName(property) %> {
- auto propertyValue = self.layer->get<%- camelize(property.name) %>() ?: self.layer->getDefault<%- camelize(property.name) %>();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->get<%- camelize(originalPropertyName(property)) %>() ?: _rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>();
+<% if (property.type == "enum") { -%>
+ return MGLStyleValueTransformer<mbgl::style::<%- mbglType(property) %>, NSValue *, mbgl::style::<%- mbglType(property) %>, MGL<%- camelize(originalPropertyName(property)) %>>().toEnumStyleValue(propertyValue);
+<% } else { -%>
return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toStyleValue(propertyValue);
+<% } -%>
}
<% } -%>
@@ -84,15 +186,29 @@
<% for (const property of paintProperties) { -%>
- (void)set<%- camelize(property.name) %>:(MGLStyleValue<<%- propertyType(property, true) %>> *)<%- objCName(property) %> {
+ MGLAssertStyleLayerIsValid();
+
+<% if (property.type == "enum") { -%>
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::<%- mbglType(property) %>, NSValue *, mbgl::style::<%- mbglType(property) %>, MGL<%- camelize(originalPropertyName(property)) %>>().toEnumPropertyValue(<%- objCName(property) %>);
+ _rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue);
+<% } else { -%>
auto mbglValue = MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toPropertyValue(<%- objCName(property) %>);
- self.layer->set<%- camelize(property.name) %>(mbglValue);
+ _rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbglValue);
+<% } -%>
}
- (MGLStyleValue<<%- propertyType(property, true) %>> *)<%- objCName(property) %> {
- auto propertyValue = self.layer->get<%- camelize(property.name) %>() ?: self.layer->getDefault<%- camelize(property.name) %>();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->get<%- camelize(originalPropertyName(property)) %>() ?: _rawLayer->getDefault<%- camelize(originalPropertyName(property)) %>();
+<% if (property.type == "enum") { -%>
+ return MGLStyleValueTransformer<mbgl::style::<%- mbglType(property) %>, NSValue *, mbgl::style::<%- mbglType(property) %>, MGL<%- camelize(originalPropertyName(property)) %>>().toEnumStyleValue(propertyValue);
+<% } else { -%>
return MGLStyleValueTransformer<<%- valueTransformerArguments(property).join(', ') %>>().toStyleValue(propertyValue);
+<% } -%>
}
<% } -%>
<% } -%>
+
@end
diff --git a/platform/darwin/src/MGLStyleLayer_Private.h b/platform/darwin/src/MGLStyleLayer_Private.h
index 5fa01856ea..e723c8cf1b 100644
--- a/platform/darwin/src/MGLStyleLayer_Private.h
+++ b/platform/darwin/src/MGLStyleLayer_Private.h
@@ -5,9 +5,65 @@
#include <mbgl/style/layer.hpp>
+/**
+ Assert that the style layer is valid.
+
+ This macro should be used at the beginning of any public-facing instance method
+ of `MGLStyleLayer` and its subclasses. For private methods, an assertion is more appropriate.
+ */
+#define MGLAssertStyleLayerIsValid() \
+ do { \
+ if (!self.rawLayer) { \
+ [NSException raise:@"Invalid style layer" \
+ format: \
+ @"-[MGLStyle removeLayer:] has been called " \
+ @"with this instance but another style layer instance was added with the same identifer. It is an " \
+ @"error to send any message to this layer since it cannot be recovered after removal due to the " \
+ @"identifer collision. Use unique identifiers for all layer instances including layers of " \
+ @"different types."]; \
+ } \
+ } while (NO);
+
+@class MGLMapView;
+
@interface MGLStyleLayer (Private)
@property (nonatomic, readwrite, copy) NSString *identifier;
-@property (nonatomic) mbgl::style::Layer *layer;
+
+/**
+ A raw pointer to the mbgl object, which is always initialized, either to the
+ value returned by `mbgl::Map getLayer`, or for independently created objects,
+ to the pointer value held in `pendingLayer`. In the latter case, this raw
+ pointer value stays even after ownership of the object is transferred via
+ `mbgl::Map addLayer`.
+ */
+@property (nonatomic) mbgl::style::Layer *rawLayer;
+
+/**
+ Adds the mbgl style layer that this object represents to the mbgl map.
+
+ Once a mbgl style layer is added, ownership of the object is transferred to the
+ `mbgl::Map` and this object no longer has an active unique_ptr reference to the
+ `mbgl::style::Layer`.
+ */
+- (void)addToMapView:(MGLMapView *)mapView;
+
+/**
+ Removes the mbgl style layer that this object represents from the mbgl map.
+
+ When a mbgl style layer is removed, ownership of the object is transferred back
+ to the `MGLStyleLayer` instance and the unique_ptr reference is valid again. It
+ is safe to add the layer back to the style after it is removed.
+ */
+- (void)removeFromMapView:(MGLMapView *)mapView;
+
+/**
+ Adds the mbgl style layer that this object represents to the mbgl map below the specified `otherLayer`.
+
+ Once a mbgl style layer is added, ownership of the object is transferred to the
+ `mbgl::Map` and this object no longer has an active unique_ptr reference to the
+ `mbgl::style::Layer`.
+ */
+- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer;
@end
diff --git a/platform/darwin/src/MGLStyleValue_Private.h b/platform/darwin/src/MGLStyleValue_Private.h
index fdad07aafa..492ce20f1a 100644
--- a/platform/darwin/src/MGLStyleValue_Private.h
+++ b/platform/darwin/src/MGLStyleValue_Private.h
@@ -4,6 +4,8 @@
#import "NSValue+MGLStyleAttributeAdditions.h"
#import "MGLTypes.h"
+#import "MGLLineStyleLayer.h"
+#import <mbgl/util/enum.hpp>
#if TARGET_OS_IPHONE
#import "UIColor+MGLAdditions.h"
@@ -13,7 +15,7 @@
#include <array>
-template <typename MBGLType, typename ObjCType, typename MBGLElement = MBGLType>
+template <typename MBGLType, typename ObjCType, typename MBGLElement = MBGLType, typename ObjCEnum = ObjCType>
class MGLStyleValueTransformer {
public:
@@ -26,7 +28,26 @@ public:
return nil;
}
}
-
+
+ template <typename MBGLEnum = MBGLType,
+ class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type,
+ typename MGLEnum = ObjCEnum,
+ class = typename std::enable_if<std::is_enum<MGLEnum>::value>::type>
+ MGLStyleValue<ObjCType> *toEnumStyleValue(const mbgl::style::PropertyValue<MBGLEnum> &mbglValue) {
+ if (mbglValue.isConstant()) {
+ return toEnumStyleConstantValue<>(mbglValue.asConstant());
+ } else if (mbglValue.isFunction()) {
+ const auto &mbglStops = mbglValue.asFunction().getStops();
+ NSMutableDictionary *stops = [NSMutableDictionary dictionaryWithCapacity:mbglStops.size()];
+ for (const auto &mbglStop : mbglStops) {
+ stops[@(mbglStop.first)] = toEnumStyleConstantValue<>(mbglStop.second);
+ }
+ return [MGLStyleFunction<NSValue *> functionWithBase:mbglValue.asFunction().getBase() stops:stops];
+ } else {
+ return nil;
+ }
+ }
+
mbgl::style::PropertyValue<MBGLType> toPropertyValue(MGLStyleValue<ObjCType> *value) {
if ([value isKindOfClass:[MGLStyleConstantValue class]]) {
MBGLType mbglValue;
@@ -52,9 +73,39 @@ public:
return {};
}
}
-
+
+ template <typename MBGLEnum = MBGLType,
+ class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type,
+ typename MGLEnum = ObjCEnum,
+ class = typename std::enable_if<std::is_enum<MGLEnum>::value>::type>
+ mbgl::style::PropertyValue<MBGLEnum> toEnumPropertyValue(MGLStyleValue<ObjCType> *value) {
+ if ([value isKindOfClass:[MGLStyleConstantValue class]]) {
+ MBGLEnum mbglValue;
+ getMBGLValue([(MGLStyleConstantValue<ObjCType> *)value rawValue], mbglValue);
+ return mbglValue;
+ } else if ([value isKindOfClass:[MGLStyleFunction class]]) {
+ MGLStyleFunction<NSValue *> *function = (MGLStyleFunction<NSValue *> *)value;
+ __block std::vector<std::pair<float, MBGLEnum>> mbglStops;
+ [function.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleValue<NSValue *> * _Nonnull stopValue, BOOL * _Nonnull stop) {
+ NSCAssert([stopValue isKindOfClass:[MGLStyleValue class]], @"Stops should be MGLStyleValues");
+ auto mbglStopValue = toEnumPropertyValue(stopValue);
+ NSCAssert(mbglStopValue.isConstant(), @"Stops must be constant");
+ mbglStops.emplace_back(zoomKey.floatValue, mbglStopValue.asConstant());
+ }];
+ return mbgl::style::Function<MBGLEnum>({{mbglStops}}, function.base);
+ } else if (value) {
+ [NSException raise:@"MGLAbstractClassException" format:
+ @"The style value %@ cannot be applied to the style. "
+ @"Make sure the style value was created as a member of a concrete subclass of MGLStyleValue.",
+ NSStringFromClass([value class])];
+ return {};
+ } else {
+ return {};
+ }
+ }
+
private:
-
+
MGLStyleConstantValue<ObjCType> *toStyleConstantValue(const MBGLType mbglValue) {
auto rawValue = toMGLRawStyleValue(mbglValue);
return [MGLStyleConstantValue<ObjCType> valueWithRawValue:rawValue];
@@ -69,7 +120,17 @@ private:
}
return [MGLStyleFunction<ObjCType> functionWithBase:mbglFunction.getBase() stops:stops];
}
-
+
+ template <typename MBGLEnum = MBGLType,
+ class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type,
+ typename MGLEnum = ObjCEnum,
+ class = typename std::enable_if<std::is_enum<MGLEnum>::value>::type>
+ MGLStyleConstantValue<ObjCType> *toEnumStyleConstantValue(const MBGLEnum mbglValue) {
+ auto str = mbgl::Enum<MBGLEnum>::toString(mbglValue);
+ MGLEnum mglType = *mbgl::Enum<MGLEnum>::toEnum(str);
+ return [MGLStyleConstantValue<ObjCType> valueWithRawValue:[NSValue value:&mglType withObjCType:@encode(MGLEnum)]];
+ }
+
NSNumber *toMGLRawStyleValue(const bool mbglStopValue) {
return @(mbglStopValue);
}
@@ -92,13 +153,6 @@ private:
return [NSValue mgl_valueWithPaddingArray:mbglStopValue];
}
- // Enumerations
- template <typename MBGLEnum = MBGLType, class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type>
- ObjCType toMGLRawStyleValue(const MBGLType &mbglStopValue) {
- NSUInteger rawValue = static_cast<NSUInteger>(mbglStopValue);
- return [NSValue value:&rawValue withObjCType:@encode(NSUInteger)];
- }
-
MGLColor *toMGLRawStyleValue(const mbgl::Color mbglStopValue) {
return [MGLColor mgl_colorWithColor:mbglStopValue];
}
@@ -110,9 +164,9 @@ private:
}
return array;
}
-
+
private:
-
+
void getMBGLValue(NSNumber *rawValue, bool &mbglValue) {
mbglValue = !!rawValue.boolValue;
}
@@ -135,12 +189,6 @@ private:
mbglValue = rawValue.mgl_paddingArrayValue;
}
- // Enumerations
- template <typename MBGLEnum = MBGLType, class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type>
- void getMBGLValue(ObjCType rawValue, MBGLType &mbglValue) {
- [rawValue getValue:&mbglValue];
- }
-
void getMBGLValue(MGLColor *rawValue, mbgl::Color &mbglValue) {
mbglValue = rawValue.mgl_color;
}
@@ -153,4 +201,16 @@ private:
mbglValue.push_back(mbglElement);
}
}
+
+ // Enumerations
+ template <typename MBGLEnum = MBGLType,
+ class = typename std::enable_if<std::is_enum<MBGLEnum>::value>::type,
+ typename MGLEnum = ObjCEnum,
+ class = typename std::enable_if<std::is_enum<MGLEnum>::value>::type>
+ void getMBGLValue(ObjCType rawValue, MBGLEnum &mbglValue) {
+ MGLEnum mglEnum;
+ [rawValue getValue:&mglEnum];
+ auto str = mbgl::Enum<MGLEnum>::toString(mglEnum);
+ mbglValue = *mbgl::Enum<MBGLEnum>::toEnum(str);
+ }
};
diff --git a/platform/darwin/src/MGLStyle_Private.h b/platform/darwin/src/MGLStyle_Private.h
index 6f52b67fa7..002be884e4 100644
--- a/platform/darwin/src/MGLStyle_Private.h
+++ b/platform/darwin/src/MGLStyle_Private.h
@@ -5,7 +5,10 @@
#import <mbgl/util/default_styles.hpp>
@interface MGLStyle (Private)
-@property (nonatomic, weak) MGLMapView *mapView;
+
+- (instancetype)initWithMapView:(MGLMapView *)mapView;
+
+@property (nonatomic, readonly, weak) MGLMapView *mapView;
- (void)setStyleClasses:(NS_ARRAY_OF(NSString *) *)appliedClasses transitionDuration:(NSTimeInterval)transitionDuration;
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h
index dc0cd236c8..dbb966b4e6 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.h
+++ b/platform/darwin/src/MGLSymbolStyleLayer.h
@@ -7,22 +7,6 @@
NS_ASSUME_NONNULL_BEGIN
/**
- Label placement relative to its geometry.
-
- Values of this type are used in the `symbolPlacement` property of `MGLSymbolStyleLayer`.
- */
-typedef NS_ENUM(NSUInteger, MGLSymbolPlacement) {
- /**
- The label is placed at the point where the geometry is located.
- */
- MGLSymbolPlacementPoint,
- /**
- The label is placed along the line of the geometry. Can only be used on `LineString` and `Polygon` geometries.
- */
- MGLSymbolPlacementLine,
-};
-
-/**
In combination with `symbolPlacement`, determines the rotation behavior of icons.
Values of this type are used in the `iconRotationAlignment` property of `MGLSymbolStyleLayer`.
@@ -67,43 +51,63 @@ typedef NS_ENUM(NSUInteger, MGLIconTextFit) {
};
/**
- Orientation of text when map is pitched.
+ Label placement relative to its geometry.
- Values of this type are used in the `textPitchAlignment` property of `MGLSymbolStyleLayer`.
+ Values of this type are used in the `symbolPlacement` property of `MGLSymbolStyleLayer`.
*/
-typedef NS_ENUM(NSUInteger, MGLTextPitchAlignment) {
- /**
- The text is aligned to the plane of the map.
- */
- MGLTextPitchAlignmentMap,
+typedef NS_ENUM(NSUInteger, MGLSymbolPlacement) {
/**
- The text is aligned to the plane of the viewport.
+ The label is placed at the point where the geometry is located.
*/
- MGLTextPitchAlignmentViewport,
+ MGLSymbolPlacementPoint,
/**
- Automatically matches the value of `textRotationAlignment`.
+ The label is placed along the line of the geometry. Can only be used on `LineString` and `Polygon` geometries.
*/
- MGLTextPitchAlignmentAuto,
+ MGLSymbolPlacementLine,
};
/**
- In combination with `symbolPlacement`, determines the rotation behavior of the individual glyphs forming the text.
+ Part of the text placed closest to the anchor.
- Values of this type are used in the `textRotationAlignment` property of `MGLSymbolStyleLayer`.
+ Values of this type are used in the `textAnchor` property of `MGLSymbolStyleLayer`.
*/
-typedef NS_ENUM(NSUInteger, MGLTextRotationAlignment) {
+typedef NS_ENUM(NSUInteger, MGLTextAnchor) {
/**
- When `symbolPlacement` is set to `MGLSymbolPlacementPoint`, aligns text east-west. When `symbolPlacement` is set to `MGLSymbolPlacementLine`, aligns text x-axes with the line.
+ The center of the text is placed closest to the anchor.
*/
- MGLTextRotationAlignmentMap,
+ MGLTextAnchorCenter,
/**
- Produces glyphs whose x-axes are aligned with the x-axis of the viewport, regardless of the value of `symbolPlacement`.
+ The left side of the text is placed closest to the anchor.
*/
- MGLTextRotationAlignmentViewport,
+ MGLTextAnchorLeft,
/**
- When `symbolPlacement` is set to `MGLSymbolPlacementPoint`, this is equivalent to `MGLTextRotationAlignmentViewport`. When `symbolPlacement` is set to `MGLSymbolPlacementLine`, this is equivalent to `MGLTextRotationAlignmentMap`.
+ The right side of the text is placed closest to the anchor.
*/
- MGLTextRotationAlignmentAuto,
+ MGLTextAnchorRight,
+ /**
+ The top of the text is placed closest to the anchor.
+ */
+ MGLTextAnchorTop,
+ /**
+ The bottom of the text is placed closest to the anchor.
+ */
+ MGLTextAnchorBottom,
+ /**
+ The top left corner of the text is placed closest to the anchor.
+ */
+ MGLTextAnchorTopLeft,
+ /**
+ The top right corner of the text is placed closest to the anchor.
+ */
+ MGLTextAnchorTopRight,
+ /**
+ The bottom left corner of the text is placed closest to the anchor.
+ */
+ MGLTextAnchorBottomLeft,
+ /**
+ The bottom right corner of the text is placed closest to the anchor.
+ */
+ MGLTextAnchorBottomRight,
};
/**
@@ -127,47 +131,43 @@ typedef NS_ENUM(NSUInteger, MGLTextJustify) {
};
/**
- Part of the text placed closest to the anchor.
+ Orientation of text when map is pitched.
- Values of this type are used in the `textAnchor` property of `MGLSymbolStyleLayer`.
+ Values of this type are used in the `textPitchAlignment` property of `MGLSymbolStyleLayer`.
*/
-typedef NS_ENUM(NSUInteger, MGLTextAnchor) {
- /**
- The center of the text is placed closest to the anchor.
- */
- MGLTextAnchorCenter,
- /**
- The left side of the text is placed closest to the anchor.
- */
- MGLTextAnchorLeft,
- /**
- The right side of the text is placed closest to the anchor.
- */
- MGLTextAnchorRight,
+typedef NS_ENUM(NSUInteger, MGLTextPitchAlignment) {
/**
- The top of the text is placed closest to the anchor.
+ The text is aligned to the plane of the map.
*/
- MGLTextAnchorTop,
+ MGLTextPitchAlignmentMap,
/**
- The bottom of the text is placed closest to the anchor.
+ The text is aligned to the plane of the viewport.
*/
- MGLTextAnchorBottom,
+ MGLTextPitchAlignmentViewport,
/**
- The top left corner of the text is placed closest to the anchor.
+ Automatically matches the value of `textRotationAlignment`.
*/
- MGLTextAnchorTopLeft,
+ MGLTextPitchAlignmentAuto,
+};
+
+/**
+ In combination with `symbolPlacement`, determines the rotation behavior of the individual glyphs forming the text.
+
+ Values of this type are used in the `textRotationAlignment` property of `MGLSymbolStyleLayer`.
+ */
+typedef NS_ENUM(NSUInteger, MGLTextRotationAlignment) {
/**
- The top right corner of the text is placed closest to the anchor.
+ When `symbolPlacement` is set to `MGLSymbolPlacementPoint`, aligns text east-west. When `symbolPlacement` is set to `MGLSymbolPlacementLine`, aligns text x-axes with the line.
*/
- MGLTextAnchorTopRight,
+ MGLTextRotationAlignmentMap,
/**
- The bottom left corner of the text is placed closest to the anchor.
+ Produces glyphs whose x-axes are aligned with the x-axis of the viewport, regardless of the value of `symbolPlacement`.
*/
- MGLTextAnchorBottomLeft,
+ MGLTextRotationAlignmentViewport,
/**
- The bottom right corner of the text is placed closest to the anchor.
+ When `symbolPlacement` is set to `MGLSymbolPlacementPoint`, this is equivalent to `MGLTextRotationAlignmentViewport`. When `symbolPlacement` is set to `MGLSymbolPlacementLine`, this is equivalent to `MGLTextRotationAlignmentMap`.
*/
- MGLTextAnchorBottomRight,
+ MGLTextRotationAlignmentAuto,
};
/**
@@ -233,47 +233,45 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) {
#pragma mark - Accessing the Layout Attributes
/**
- Label placement relative to its geometry.
+ If true, the icon will be visible even if it collides with other previously drawn symbols.
- The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementPoint`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value.
+
+ This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *symbolPlacement;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconAllowOverlap;
/**
- Distance between two symbol anchors.
-
- This property is measured in points.
+ If true, other symbols can be visible even if they collide with the icon.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `250`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. 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 `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored.
+ This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *symbolSpacing;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconIgnorePlacement;
/**
- 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.
-
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value.
+ A string with {tokens} replaced, referencing the data property to pull from.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *symbolAvoidEdges;
+@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *iconImageName;
/**
- If true, the icon will be visible even if it collides with other previously drawn symbols.
+ If true, the icon may be flipped to prevent it from being rendered upside-down.
The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value.
- This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored.
+ This property is only applied to the style if `iconImage` is non-`nil`, and `iconRotationAlignment` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconRotationAlignmentMap`, and `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconAllowOverlap;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconKeepUpright;
/**
- If true, other symbols can be visible even if they collide with the icon.
+ Offset distance of icon from its anchor.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 from the left and 0 from the top. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconIgnorePlacement;
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconOffset;
/**
If true, text will display without their corresponding icons when the icon collides with other symbols and the text does not.
@@ -285,6 +283,28 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) {
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconOptional;
/**
+ Size of the additional area around the icon bounding box used for detecting symbol collisions.
+
+ This property is measured in points.
+
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `2`. Set this property to `nil` to reset it to the default value.
+
+ This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored.
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconPadding;
+
+/**
+ Rotates the icon clockwise.
+
+ This property is measured in degrees.
+
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
+
+ This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored.
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconRotate;
+
+/**
In combination with `symbolPlacement`, determines the rotation behavior of icons.
The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconRotationAlignmentAuto`. Set this property to `nil` to reset it to the default value.
@@ -323,67 +343,47 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) {
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconTextFitPadding;
/**
- A string with {tokens} replaced, referencing the data property to pull from.
+ 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.
+
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSString *> *iconImage;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *symbolAvoidEdges;
/**
- Rotates the icon clockwise.
-
- This property is measured in degrees.
-
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
+ Label placement relative to its geometry.
- This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored.
+ The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementPoint`. Set this property to `nil` to reset it to the default value.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconRotate;
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *symbolPlacement;
/**
- Size of the additional area around the icon bounding box used for detecting symbol collisions.
+ Distance between two symbol anchors.
This property is measured in points.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `2`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `250`. Set this property to `nil` to reset it to the default value.
- This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored.
+ This property is only applied to the style if `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconPadding;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *symbolSpacing;
/**
- If true, the icon may be flipped to prevent it from being rendered upside-down.
+ If true, the text will be visible even if it collides with other previously drawn symbols.
The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value.
- This property is only applied to the style if `iconImage` is non-`nil`, and `iconRotationAlignment` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLIconRotationAlignmentMap`, and `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored.
- */
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconKeepUpright;
-
-/**
- Offset distance of icon from its anchor.
-
- The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 from the left and 0 from the top. Set this property to `nil` to reset it to the default value.
-
- This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored.
- */
-@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconOffset;
-
-/**
- Orientation of text when map is pitched.
-
- The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextPitchAlignmentAuto`. Set this property to `nil` to reset it to the default value.
-
This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textPitchAlignment;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textAllowOverlap;
/**
- In combination with `symbolPlacement`, determines the rotation behavior of the individual glyphs forming the text.
+ Part of the text placed closest to the anchor.
- The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextRotationAlignmentAuto`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextAnchorCenter`. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textRotationAlignment;
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textAnchor;
/**
Value to use for a text label. Feature properties are specified using tokens like {field_name}.
@@ -402,37 +402,31 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) {
@property (nonatomic, null_resettable) MGLStyleValue<NSArray<NSString *> *> *textFont;
/**
- Font size.
-
- This property is measured in points.
+ If true, other symbols can be visible even if they collide with the text.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `16`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textSize;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textIgnorePlacement;
/**
- The maximum line width for text wrapping.
-
- This property is measured in ems.
+ Text justification options.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `10`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextJustifyCenter`. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textMaxWidth;
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textJustify;
/**
- Text leading value for multi-line text.
-
- This property is measured in ems.
+ If true, the text may be flipped vertically to prevent it from being rendered upside-down.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1.2`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `YES`. Set this property to `nil` to reset it to the default value.
- This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
+ This property is only applied to the style if `textField` is non-`nil`, and `textRotationAlignment` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextRotationAlignmentMap`, and `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textLineHeight;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textKeepUpright;
/**
Text tracking amount.
@@ -446,22 +440,15 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) {
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textLetterSpacing;
/**
- Text justification options.
-
- The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextJustifyCenter`. Set this property to `nil` to reset it to the default value.
-
- This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
- */
-@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textJustify;
+ Text leading value for multi-line text.
-/**
- Part of the text placed closest to the anchor.
+ This property is measured in ems.
- The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextAnchorCenter`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1.2`. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textAnchor;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textLineHeight;
/**
Maximum angle change between adjacent characters.
@@ -475,93 +462,97 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) {
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textMaxAngle;
/**
- Rotates the text clockwise.
+ The maximum line width for text wrapping.
- This property is measured in degrees.
+ This property is measured in ems.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `10`. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textRotate;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textMaxWidth;
/**
- Size of the additional area around the text bounding box used for detecting symbol collisions.
+ Offset distance of text from its anchor.
- This property is measured in points.
+ This property is measured in ems.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `2`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 ems from the left and 0 ems from the top. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textPadding;
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textOffset;
/**
- If true, the text may be flipped vertically to prevent it from being rendered upside-down.
+ If true, icons will display without their corresponding text when the text collides with other symbols and the icon does not.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `YES`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value.
- This property is only applied to the style if `textField` is non-`nil`, and `textRotationAlignment` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextRotationAlignmentMap`, and `symbolPlacement` is set to an `MGLStyleValue` object containing an `NSValue` object containing `MGLSymbolPlacementLine`. Otherwise, it is ignored.
+ This property is only applied to the style if `textField` is non-`nil`, and `iconImage` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textKeepUpright;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textOptional;
/**
- Specifies how to capitalize text.
+ Size of the additional area around the text bounding box used for detecting symbol collisions.
+
+ This property is measured in points.
- The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextTransformNone`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `2`. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textTransform;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textPadding;
/**
- Offset distance of text from its anchor.
-
- This property is measured in ems.
+ Orientation of text when map is pitched.
- The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing a `CGVector` struct set to 0 ems from the left and 0 ems from the top. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextPitchAlignmentAuto`. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textOffset;
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textPitchAlignment;
/**
- If true, the text will be visible even if it collides with other previously drawn symbols.
+ Rotates the text clockwise.
+
+ This property is measured in degrees.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textAllowOverlap;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textRotate;
/**
- If true, other symbols can be visible even if they collide with the text.
+ In combination with `symbolPlacement`, determines the rotation behavior of the individual glyphs forming the text.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextRotationAlignmentAuto`. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textIgnorePlacement;
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textRotationAlignment;
/**
- If true, icons will display without their corresponding text when the text collides with other symbols and the icon does not.
+ Font size.
+
+ This property is measured in points.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing `NO`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `16`. Set this property to `nil` to reset it to the default value.
- This property is only applied to the style if `textField` is non-`nil`, and `iconImage` is non-`nil`. Otherwise, it is ignored.
+ This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textOptional;
-
-#pragma mark - Accessing the Paint Attributes
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textSize;
/**
- The opacity at which the icon will be drawn.
+ Specifies how to capitalize text.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
-
- This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored.
+ The default value of this property is an `MGLStyleValue` object containing an `NSValue` object containing `MGLTextTransformNone`. Set this property to `nil` to reset it to the default value.
+
+ This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconOpacity;
+@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *textTransform;
+
+#pragma mark - Accessing the Paint Attributes
#if TARGET_OS_IPHONE
/**
@@ -583,6 +574,17 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) {
@property (nonatomic, null_resettable) MGLStyleValue<MGLColor *> *iconColor;
#endif
+/**
+ Fade out the halo towards the outside.
+
+ This property is measured in points.
+
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
+
+ This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored.
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconHaloBlur;
+
#if TARGET_OS_IPHONE
/**
The color of the icon's halo. Icon halos can only be used with SDF icons.
@@ -615,15 +617,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) {
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconHaloWidth;
/**
- Fade out the halo towards the outside.
-
- This property is measured in points.
+ The opacity at which the icon will be drawn.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `iconImage` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconHaloBlur;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *iconOpacity;
/**
Distance that the icon's anchor is moved from its original placement.
@@ -645,15 +645,6 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) {
*/
@property (nonatomic, null_resettable) MGLStyleValue<NSValue *> *iconTranslateAnchor;
-/**
- The opacity at which the text will be drawn.
-
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
-
- This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
- */
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textOpacity;
-
#if TARGET_OS_IPHONE
/**
The color with which the text will be drawn.
@@ -674,6 +665,17 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) {
@property (nonatomic, null_resettable) MGLStyleValue<MGLColor *> *textColor;
#endif
+/**
+ The halo's fadeout distance towards the outside.
+
+ This property is measured in points.
+
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
+
+ This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
+ */
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textHaloBlur;
+
#if TARGET_OS_IPHONE
/**
The color of the text's halo, which helps it stand out from backgrounds.
@@ -706,15 +708,13 @@ typedef NS_ENUM(NSUInteger, MGLTextTranslateAnchor) {
@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textHaloWidth;
/**
- The halo's fadeout distance towards the outside.
-
- This property is measured in points.
+ The opacity at which the text will be drawn.
- The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `0`. Set this property to `nil` to reset it to the default value.
+ The default value of this property is an `MGLStyleValue` object containing an `NSNumber` object containing the float `1`. Set this property to `nil` to reset it to the default value.
This property is only applied to the style if `textField` is non-`nil`. Otherwise, it is ignored.
*/
-@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textHaloBlur;
+@property (nonatomic, null_resettable) MGLStyleValue<NSNumber *> *textOpacity;
/**
Distance that the text's anchor is moved from its original placement.
diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm
index a4c56fe297..d1d66f8ffb 100644
--- a/platform/darwin/src/MGLSymbolStyleLayer.mm
+++ b/platform/darwin/src/MGLSymbolStyleLayer.mm
@@ -2,532 +2,848 @@
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
#import "MGLSource.h"
+#import "MGLMapView_Private.h"
#import "NSPredicate+MGLAdditions.h"
#import "MGLStyleLayer_Private.h"
#import "MGLStyleValue_Private.h"
#import "MGLSymbolStyleLayer.h"
#include <mbgl/style/layers/symbol_layer.hpp>
+namespace mbgl {
+
+ MBGL_DEFINE_ENUM(MGLIconRotationAlignment, {
+ { MGLIconRotationAlignmentMap, "map" },
+ { MGLIconRotationAlignmentViewport, "viewport" },
+ { MGLIconRotationAlignmentAuto, "auto" },
+ });
+
+ MBGL_DEFINE_ENUM(MGLIconTextFit, {
+ { MGLIconTextFitNone, "none" },
+ { MGLIconTextFitWidth, "width" },
+ { MGLIconTextFitHeight, "height" },
+ { MGLIconTextFitBoth, "both" },
+ });
+
+ MBGL_DEFINE_ENUM(MGLSymbolPlacement, {
+ { MGLSymbolPlacementPoint, "point" },
+ { MGLSymbolPlacementLine, "line" },
+ });
+
+ MBGL_DEFINE_ENUM(MGLTextAnchor, {
+ { MGLTextAnchorCenter, "center" },
+ { MGLTextAnchorLeft, "left" },
+ { MGLTextAnchorRight, "right" },
+ { MGLTextAnchorTop, "top" },
+ { MGLTextAnchorBottom, "bottom" },
+ { MGLTextAnchorTopLeft, "top-left" },
+ { MGLTextAnchorTopRight, "top-right" },
+ { MGLTextAnchorBottomLeft, "bottom-left" },
+ { MGLTextAnchorBottomRight, "bottom-right" },
+ });
+
+ MBGL_DEFINE_ENUM(MGLTextJustify, {
+ { MGLTextJustifyLeft, "left" },
+ { MGLTextJustifyCenter, "center" },
+ { MGLTextJustifyRight, "right" },
+ });
+
+ MBGL_DEFINE_ENUM(MGLTextPitchAlignment, {
+ { MGLTextPitchAlignmentMap, "map" },
+ { MGLTextPitchAlignmentViewport, "viewport" },
+ { MGLTextPitchAlignmentAuto, "auto" },
+ });
+
+ MBGL_DEFINE_ENUM(MGLTextRotationAlignment, {
+ { MGLTextRotationAlignmentMap, "map" },
+ { MGLTextRotationAlignmentViewport, "viewport" },
+ { MGLTextRotationAlignmentAuto, "auto" },
+ });
+
+ MBGL_DEFINE_ENUM(MGLTextTransform, {
+ { MGLTextTransformNone, "none" },
+ { MGLTextTransformUppercase, "uppercase" },
+ { MGLTextTransformLowercase, "lowercase" },
+ });
+
+ MBGL_DEFINE_ENUM(MGLIconTranslateAnchor, {
+ { MGLIconTranslateAnchorMap, "map" },
+ { MGLIconTranslateAnchorViewport, "viewport" },
+ });
+
+ MBGL_DEFINE_ENUM(MGLTextTranslateAnchor, {
+ { MGLTextTranslateAnchorMap, "map" },
+ { MGLTextTranslateAnchorViewport, "viewport" },
+ });
+
+}
@interface MGLSymbolStyleLayer ()
-@property (nonatomic) mbgl::style::SymbolLayer *layer;
+@property (nonatomic) mbgl::style::SymbolLayer *rawLayer;
@end
@implementation MGLSymbolStyleLayer
+{
+ std::unique_ptr<mbgl::style::SymbolLayer> _pendingLayer;
+}
- (instancetype)initWithIdentifier:(NSString *)identifier source:(MGLSource *)source
{
if (self = [super initWithIdentifier:identifier source:source]) {
- _layer = new mbgl::style::SymbolLayer(identifier.UTF8String, source.identifier.UTF8String);
+ auto layer = std::make_unique<mbgl::style::SymbolLayer>(identifier.UTF8String, source.identifier.UTF8String);
+ _pendingLayer = std::move(layer);
+ _rawLayer = _pendingLayer.get();
}
return self;
}
-
- (NSString *)sourceLayerIdentifier
{
- auto layerID = self.layer->getSourceLayer();
+ MGLAssertStyleLayerIsValid();
+
+ auto layerID = _rawLayer->getSourceLayer();
return layerID.empty() ? nil : @(layerID.c_str());
}
- (void)setSourceLayerIdentifier:(NSString *)sourceLayerIdentifier
{
- self.layer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: "");
+ MGLAssertStyleLayerIsValid();
+
+ _rawLayer->setSourceLayer(sourceLayerIdentifier.UTF8String ?: "");
}
- (void)setPredicate:(NSPredicate *)predicate
{
- self.layer->setFilter(predicate.mgl_filter);
+ MGLAssertStyleLayerIsValid();
+
+ _rawLayer->setFilter(predicate.mgl_filter);
}
- (NSPredicate *)predicate
{
- return [NSPredicate mgl_predicateWithFilter:self.layer->getFilter()];
+ MGLAssertStyleLayerIsValid();
+
+ return [NSPredicate mgl_predicateWithFilter:_rawLayer->getFilter()];
}
+#pragma mark - Adding to and removing from a map view
-#pragma mark - Accessing the Layout Attributes
+- (void)addToMapView:(MGLMapView *)mapView
+{
+ if (_pendingLayer == nullptr) {
+ [NSException raise:@"MGLRedundantLayerException"
+ format:@"This instance %@ was already added to %@. Adding the same layer instance " \
+ "to the style more than once is invalid.", self, mapView.style];
+ }
-- (void)setSymbolPlacement:(MGLStyleValue<NSValue *> *)symbolPlacement {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::SymbolPlacementType, NSValue *>().toPropertyValue(symbolPlacement);
- self.layer->setSymbolPlacement(mbglValue);
+ [self addToMapView:mapView belowLayer:nil];
}
-- (MGLStyleValue<NSValue *> *)symbolPlacement {
- auto propertyValue = self.layer->getSymbolPlacement() ?: self.layer->getDefaultSymbolPlacement();
- return MGLStyleValueTransformer<mbgl::style::SymbolPlacementType, NSValue *>().toStyleValue(propertyValue);
+- (void)addToMapView:(MGLMapView *)mapView belowLayer:(MGLStyleLayer *)otherLayer
+{
+ if (otherLayer) {
+ const mbgl::optional<std::string> belowLayerId{otherLayer.identifier.UTF8String};
+ mapView.mbglMap->addLayer(std::move(_pendingLayer), belowLayerId);
+ } else {
+ mapView.mbglMap->addLayer(std::move(_pendingLayer));
+ }
}
-- (void)setSymbolSpacing:(MGLStyleValue<NSNumber *> *)symbolSpacing {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(symbolSpacing);
- self.layer->setSymbolSpacing(mbglValue);
-}
+- (void)removeFromMapView:(MGLMapView *)mapView
+{
+ _pendingLayer = nullptr;
+ _rawLayer = nullptr;
-- (MGLStyleValue<NSNumber *> *)symbolSpacing {
- auto propertyValue = self.layer->getSymbolSpacing() ?: self.layer->getDefaultSymbolSpacing();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
-}
+ auto removedLayer = mapView.mbglMap->removeLayer(self.identifier.UTF8String);
+ if (!removedLayer) {
+ return;
+ }
-- (void)setSymbolAvoidEdges:(MGLStyleValue<NSNumber *> *)symbolAvoidEdges {
- auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(symbolAvoidEdges);
- self.layer->setSymbolAvoidEdges(mbglValue);
-}
+ mbgl::style::SymbolLayer *layer = dynamic_cast<mbgl::style::SymbolLayer *>(removedLayer.get());
+ if (!layer) {
+ return;
+ }
-- (MGLStyleValue<NSNumber *> *)symbolAvoidEdges {
- auto propertyValue = self.layer->getSymbolAvoidEdges() ?: self.layer->getDefaultSymbolAvoidEdges();
- return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
+ removedLayer.release();
+
+ _pendingLayer = std::unique_ptr<mbgl::style::SymbolLayer>(layer);
+ _rawLayer = _pendingLayer.get();
}
+#pragma mark - Accessing the Layout Attributes
+
- (void)setIconAllowOverlap:(MGLStyleValue<NSNumber *> *)iconAllowOverlap {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(iconAllowOverlap);
- self.layer->setIconAllowOverlap(mbglValue);
+ _rawLayer->setIconAllowOverlap(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)iconAllowOverlap {
- auto propertyValue = self.layer->getIconAllowOverlap() ?: self.layer->getDefaultIconAllowOverlap();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconAllowOverlap() ?: _rawLayer->getDefaultIconAllowOverlap();
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setIconIgnorePlacement:(MGLStyleValue<NSNumber *> *)iconIgnorePlacement {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(iconIgnorePlacement);
- self.layer->setIconIgnorePlacement(mbglValue);
+ _rawLayer->setIconIgnorePlacement(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)iconIgnorePlacement {
- auto propertyValue = self.layer->getIconIgnorePlacement() ?: self.layer->getDefaultIconIgnorePlacement();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconIgnorePlacement() ?: _rawLayer->getDefaultIconIgnorePlacement();
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
+}
+
+- (void)setIconImageName:(MGLStyleValue<NSString *> *)iconImageName {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toPropertyValue(iconImageName);
+ _rawLayer->setIconImage(mbglValue);
+}
+
+- (MGLStyleValue<NSString *> *)iconImageName {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconImage() ?: _rawLayer->getDefaultIconImage();
+ return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue);
+}
+
+- (void)setIconKeepUpright:(MGLStyleValue<NSNumber *> *)iconKeepUpright {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(iconKeepUpright);
+ _rawLayer->setIconKeepUpright(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)iconKeepUpright {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconKeepUpright() ?: _rawLayer->getDefaultIconKeepUpright();
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
+- (void)setIconOffset:(MGLStyleValue<NSValue *> *)iconOffset {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(iconOffset);
+ _rawLayer->setIconOffset(mbglValue);
+}
+
+- (MGLStyleValue<NSValue *> *)iconOffset {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconOffset() ?: _rawLayer->getDefaultIconOffset();
+ return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
+}
+
- (void)setIconOptional:(MGLStyleValue<NSNumber *> *)iconOptional {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(iconOptional);
- self.layer->setIconOptional(mbglValue);
+ _rawLayer->setIconOptional(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)iconOptional {
- auto propertyValue = self.layer->getIconOptional() ?: self.layer->getDefaultIconOptional();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconOptional() ?: _rawLayer->getDefaultIconOptional();
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
+- (void)setIconPadding:(MGLStyleValue<NSNumber *> *)iconPadding {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconPadding);
+ _rawLayer->setIconPadding(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)iconPadding {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconPadding() ?: _rawLayer->getDefaultIconPadding();
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+}
+
+- (void)setIconRotate:(MGLStyleValue<NSNumber *> *)iconRotate {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconRotate);
+ _rawLayer->setIconRotate(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)iconRotate {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconRotate() ?: _rawLayer->getDefaultIconRotate();
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+}
+
- (void)setIconRotationAlignment:(MGLStyleValue<NSValue *> *)iconRotationAlignment {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *>().toPropertyValue(iconRotationAlignment);
- self.layer->setIconRotationAlignment(mbglValue);
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLIconRotationAlignment>().toEnumPropertyValue(iconRotationAlignment);
+ _rawLayer->setIconRotationAlignment(mbglValue);
}
- (MGLStyleValue<NSValue *> *)iconRotationAlignment {
- auto propertyValue = self.layer->getIconRotationAlignment() ?: self.layer->getDefaultIconRotationAlignment();
- return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *>().toStyleValue(propertyValue);
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconRotationAlignment() ?: _rawLayer->getDefaultIconRotationAlignment();
+ return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLIconRotationAlignment>().toEnumStyleValue(propertyValue);
}
- (void)setIconSize:(MGLStyleValue<NSNumber *> *)iconSize {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconSize);
- self.layer->setIconSize(mbglValue);
+ _rawLayer->setIconSize(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)iconSize {
- auto propertyValue = self.layer->getIconSize() ?: self.layer->getDefaultIconSize();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconSize() ?: _rawLayer->getDefaultIconSize();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setIconTextFit:(MGLStyleValue<NSValue *> *)iconTextFit {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::IconTextFitType, NSValue *>().toPropertyValue(iconTextFit);
- self.layer->setIconTextFit(mbglValue);
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::IconTextFitType, NSValue *, mbgl::style::IconTextFitType, MGLIconTextFit>().toEnumPropertyValue(iconTextFit);
+ _rawLayer->setIconTextFit(mbglValue);
}
- (MGLStyleValue<NSValue *> *)iconTextFit {
- auto propertyValue = self.layer->getIconTextFit() ?: self.layer->getDefaultIconTextFit();
- return MGLStyleValueTransformer<mbgl::style::IconTextFitType, NSValue *>().toStyleValue(propertyValue);
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconTextFit() ?: _rawLayer->getDefaultIconTextFit();
+ return MGLStyleValueTransformer<mbgl::style::IconTextFitType, NSValue *, mbgl::style::IconTextFitType, MGLIconTextFit>().toEnumStyleValue(propertyValue);
}
- (void)setIconTextFitPadding:(MGLStyleValue<NSValue *> *)iconTextFitPadding {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<std::array<float, 4>, NSValue *>().toPropertyValue(iconTextFitPadding);
- self.layer->setIconTextFitPadding(mbglValue);
+ _rawLayer->setIconTextFitPadding(mbglValue);
}
- (MGLStyleValue<NSValue *> *)iconTextFitPadding {
- auto propertyValue = self.layer->getIconTextFitPadding() ?: self.layer->getDefaultIconTextFitPadding();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconTextFitPadding() ?: _rawLayer->getDefaultIconTextFitPadding();
return MGLStyleValueTransformer<std::array<float, 4>, NSValue *>().toStyleValue(propertyValue);
}
-- (void)setIconImage:(MGLStyleValue<NSString *> *)iconImage {
- auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toPropertyValue(iconImage);
- self.layer->setIconImage(mbglValue);
+- (void)setSymbolAvoidEdges:(MGLStyleValue<NSNumber *> *)symbolAvoidEdges {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(symbolAvoidEdges);
+ _rawLayer->setSymbolAvoidEdges(mbglValue);
}
-- (MGLStyleValue<NSString *> *)iconImage {
- auto propertyValue = self.layer->getIconImage() ?: self.layer->getDefaultIconImage();
- return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue);
+- (MGLStyleValue<NSNumber *> *)symbolAvoidEdges {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getSymbolAvoidEdges() ?: _rawLayer->getDefaultSymbolAvoidEdges();
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setIconRotate:(MGLStyleValue<NSNumber *> *)iconRotate {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconRotate);
- self.layer->setIconRotate(mbglValue);
+- (void)setSymbolPlacement:(MGLStyleValue<NSValue *> *)symbolPlacement {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::SymbolPlacementType, NSValue *, mbgl::style::SymbolPlacementType, MGLSymbolPlacement>().toEnumPropertyValue(symbolPlacement);
+ _rawLayer->setSymbolPlacement(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)iconRotate {
- auto propertyValue = self.layer->getIconRotate() ?: self.layer->getDefaultIconRotate();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+- (MGLStyleValue<NSValue *> *)symbolPlacement {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getSymbolPlacement() ?: _rawLayer->getDefaultSymbolPlacement();
+ return MGLStyleValueTransformer<mbgl::style::SymbolPlacementType, NSValue *, mbgl::style::SymbolPlacementType, MGLSymbolPlacement>().toEnumStyleValue(propertyValue);
}
-- (void)setIconPadding:(MGLStyleValue<NSNumber *> *)iconPadding {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconPadding);
- self.layer->setIconPadding(mbglValue);
+- (void)setSymbolSpacing:(MGLStyleValue<NSNumber *> *)symbolSpacing {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(symbolSpacing);
+ _rawLayer->setSymbolSpacing(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)iconPadding {
- auto propertyValue = self.layer->getIconPadding() ?: self.layer->getDefaultIconPadding();
+- (MGLStyleValue<NSNumber *> *)symbolSpacing {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getSymbolSpacing() ?: _rawLayer->getDefaultSymbolSpacing();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setIconKeepUpright:(MGLStyleValue<NSNumber *> *)iconKeepUpright {
- auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(iconKeepUpright);
- self.layer->setIconKeepUpright(mbglValue);
-}
+- (void)setTextAllowOverlap:(MGLStyleValue<NSNumber *> *)textAllowOverlap {
+ MGLAssertStyleLayerIsValid();
-- (MGLStyleValue<NSNumber *> *)iconKeepUpright {
- auto propertyValue = self.layer->getIconKeepUpright() ?: self.layer->getDefaultIconKeepUpright();
- return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
+ auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(textAllowOverlap);
+ _rawLayer->setTextAllowOverlap(mbglValue);
}
-- (void)setIconOffset:(MGLStyleValue<NSValue *> *)iconOffset {
- auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(iconOffset);
- self.layer->setIconOffset(mbglValue);
-}
+- (MGLStyleValue<NSNumber *> *)textAllowOverlap {
+ MGLAssertStyleLayerIsValid();
-- (MGLStyleValue<NSValue *> *)iconOffset {
- auto propertyValue = self.layer->getIconOffset() ?: self.layer->getDefaultIconOffset();
- return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
+ auto propertyValue = _rawLayer->getTextAllowOverlap() ?: _rawLayer->getDefaultTextAllowOverlap();
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setTextPitchAlignment:(MGLStyleValue<NSValue *> *)textPitchAlignment {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *>().toPropertyValue(textPitchAlignment);
- self.layer->setTextPitchAlignment(mbglValue);
-}
+- (void)setTextAnchor:(MGLStyleValue<NSValue *> *)textAnchor {
+ MGLAssertStyleLayerIsValid();
-- (MGLStyleValue<NSValue *> *)textPitchAlignment {
- auto propertyValue = self.layer->getTextPitchAlignment() ?: self.layer->getDefaultTextPitchAlignment();
- return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *>().toStyleValue(propertyValue);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::TextAnchorType, NSValue *, mbgl::style::TextAnchorType, MGLTextAnchor>().toEnumPropertyValue(textAnchor);
+ _rawLayer->setTextAnchor(mbglValue);
}
-- (void)setTextRotationAlignment:(MGLStyleValue<NSValue *> *)textRotationAlignment {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *>().toPropertyValue(textRotationAlignment);
- self.layer->setTextRotationAlignment(mbglValue);
-}
+- (MGLStyleValue<NSValue *> *)textAnchor {
+ MGLAssertStyleLayerIsValid();
-- (MGLStyleValue<NSValue *> *)textRotationAlignment {
- auto propertyValue = self.layer->getTextRotationAlignment() ?: self.layer->getDefaultTextRotationAlignment();
- return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *>().toStyleValue(propertyValue);
+ auto propertyValue = _rawLayer->getTextAnchor() ?: _rawLayer->getDefaultTextAnchor();
+ return MGLStyleValueTransformer<mbgl::style::TextAnchorType, NSValue *, mbgl::style::TextAnchorType, MGLTextAnchor>().toEnumStyleValue(propertyValue);
}
- (void)setTextField:(MGLStyleValue<NSString *> *)textField {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toPropertyValue(textField);
- self.layer->setTextField(mbglValue);
+ _rawLayer->setTextField(mbglValue);
}
- (MGLStyleValue<NSString *> *)textField {
- auto propertyValue = self.layer->getTextField() ?: self.layer->getDefaultTextField();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextField() ?: _rawLayer->getDefaultTextField();
return MGLStyleValueTransformer<std::string, NSString *>().toStyleValue(propertyValue);
}
- (void)setTextFont:(MGLStyleValue<NSArray<NSString *> *> *)textFont {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<std::vector<std::string>, NSArray<NSString *> *, std::string>().toPropertyValue(textFont);
- self.layer->setTextFont(mbglValue);
+ _rawLayer->setTextFont(mbglValue);
}
- (MGLStyleValue<NSArray<NSString *> *> *)textFont {
- auto propertyValue = self.layer->getTextFont() ?: self.layer->getDefaultTextFont();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextFont() ?: _rawLayer->getDefaultTextFont();
return MGLStyleValueTransformer<std::vector<std::string>, NSArray<NSString *> *, std::string>().toStyleValue(propertyValue);
}
-- (void)setTextSize:(MGLStyleValue<NSNumber *> *)textSize {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textSize);
- self.layer->setTextSize(mbglValue);
+- (void)setTextIgnorePlacement:(MGLStyleValue<NSNumber *> *)textIgnorePlacement {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(textIgnorePlacement);
+ _rawLayer->setTextIgnorePlacement(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)textSize {
- auto propertyValue = self.layer->getTextSize() ?: self.layer->getDefaultTextSize();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+- (MGLStyleValue<NSNumber *> *)textIgnorePlacement {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextIgnorePlacement() ?: _rawLayer->getDefaultTextIgnorePlacement();
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setTextMaxWidth:(MGLStyleValue<NSNumber *> *)textMaxWidth {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textMaxWidth);
- self.layer->setTextMaxWidth(mbglValue);
+- (void)setTextJustify:(MGLStyleValue<NSValue *> *)textJustify {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::TextJustifyType, NSValue *, mbgl::style::TextJustifyType, MGLTextJustify>().toEnumPropertyValue(textJustify);
+ _rawLayer->setTextJustify(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)textMaxWidth {
- auto propertyValue = self.layer->getTextMaxWidth() ?: self.layer->getDefaultTextMaxWidth();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+- (MGLStyleValue<NSValue *> *)textJustify {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextJustify() ?: _rawLayer->getDefaultTextJustify();
+ return MGLStyleValueTransformer<mbgl::style::TextJustifyType, NSValue *, mbgl::style::TextJustifyType, MGLTextJustify>().toEnumStyleValue(propertyValue);
}
-- (void)setTextLineHeight:(MGLStyleValue<NSNumber *> *)textLineHeight {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textLineHeight);
- self.layer->setTextLineHeight(mbglValue);
+- (void)setTextKeepUpright:(MGLStyleValue<NSNumber *> *)textKeepUpright {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(textKeepUpright);
+ _rawLayer->setTextKeepUpright(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)textLineHeight {
- auto propertyValue = self.layer->getTextLineHeight() ?: self.layer->getDefaultTextLineHeight();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+- (MGLStyleValue<NSNumber *> *)textKeepUpright {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextKeepUpright() ?: _rawLayer->getDefaultTextKeepUpright();
+ return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setTextLetterSpacing:(MGLStyleValue<NSNumber *> *)textLetterSpacing {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textLetterSpacing);
- self.layer->setTextLetterSpacing(mbglValue);
+ _rawLayer->setTextLetterSpacing(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)textLetterSpacing {
- auto propertyValue = self.layer->getTextLetterSpacing() ?: self.layer->getDefaultTextLetterSpacing();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextLetterSpacing() ?: _rawLayer->getDefaultTextLetterSpacing();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setTextJustify:(MGLStyleValue<NSValue *> *)textJustify {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::TextJustifyType, NSValue *>().toPropertyValue(textJustify);
- self.layer->setTextJustify(mbglValue);
-}
+- (void)setTextLineHeight:(MGLStyleValue<NSNumber *> *)textLineHeight {
+ MGLAssertStyleLayerIsValid();
-- (MGLStyleValue<NSValue *> *)textJustify {
- auto propertyValue = self.layer->getTextJustify() ?: self.layer->getDefaultTextJustify();
- return MGLStyleValueTransformer<mbgl::style::TextJustifyType, NSValue *>().toStyleValue(propertyValue);
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textLineHeight);
+ _rawLayer->setTextLineHeight(mbglValue);
}
-- (void)setTextAnchor:(MGLStyleValue<NSValue *> *)textAnchor {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::TextAnchorType, NSValue *>().toPropertyValue(textAnchor);
- self.layer->setTextAnchor(mbglValue);
-}
+- (MGLStyleValue<NSNumber *> *)textLineHeight {
+ MGLAssertStyleLayerIsValid();
-- (MGLStyleValue<NSValue *> *)textAnchor {
- auto propertyValue = self.layer->getTextAnchor() ?: self.layer->getDefaultTextAnchor();
- return MGLStyleValueTransformer<mbgl::style::TextAnchorType, NSValue *>().toStyleValue(propertyValue);
+ auto propertyValue = _rawLayer->getTextLineHeight() ?: _rawLayer->getDefaultTextLineHeight();
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setTextMaxAngle:(MGLStyleValue<NSNumber *> *)textMaxAngle {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textMaxAngle);
- self.layer->setTextMaxAngle(mbglValue);
+ _rawLayer->setTextMaxAngle(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)textMaxAngle {
- auto propertyValue = self.layer->getTextMaxAngle() ?: self.layer->getDefaultTextMaxAngle();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextMaxAngle() ?: _rawLayer->getDefaultTextMaxAngle();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setTextRotate:(MGLStyleValue<NSNumber *> *)textRotate {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textRotate);
- self.layer->setTextRotate(mbglValue);
+- (void)setTextMaxWidth:(MGLStyleValue<NSNumber *> *)textMaxWidth {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textMaxWidth);
+ _rawLayer->setTextMaxWidth(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)textRotate {
- auto propertyValue = self.layer->getTextRotate() ?: self.layer->getDefaultTextRotate();
+- (MGLStyleValue<NSNumber *> *)textMaxWidth {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextMaxWidth() ?: _rawLayer->getDefaultTextMaxWidth();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setTextPadding:(MGLStyleValue<NSNumber *> *)textPadding {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textPadding);
- self.layer->setTextPadding(mbglValue);
+- (void)setTextOffset:(MGLStyleValue<NSValue *> *)textOffset {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(textOffset);
+ _rawLayer->setTextOffset(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)textPadding {
- auto propertyValue = self.layer->getTextPadding() ?: self.layer->getDefaultTextPadding();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+- (MGLStyleValue<NSValue *> *)textOffset {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextOffset() ?: _rawLayer->getDefaultTextOffset();
+ return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
}
-- (void)setTextKeepUpright:(MGLStyleValue<NSNumber *> *)textKeepUpright {
- auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(textKeepUpright);
- self.layer->setTextKeepUpright(mbglValue);
+- (void)setTextOptional:(MGLStyleValue<NSNumber *> *)textOptional {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(textOptional);
+ _rawLayer->setTextOptional(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)textKeepUpright {
- auto propertyValue = self.layer->getTextKeepUpright() ?: self.layer->getDefaultTextKeepUpright();
+- (MGLStyleValue<NSNumber *> *)textOptional {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextOptional() ?: _rawLayer->getDefaultTextOptional();
return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setTextTransform:(MGLStyleValue<NSValue *> *)textTransform {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::TextTransformType, NSValue *>().toPropertyValue(textTransform);
- self.layer->setTextTransform(mbglValue);
+- (void)setTextPadding:(MGLStyleValue<NSNumber *> *)textPadding {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textPadding);
+ _rawLayer->setTextPadding(mbglValue);
}
-- (MGLStyleValue<NSValue *> *)textTransform {
- auto propertyValue = self.layer->getTextTransform() ?: self.layer->getDefaultTextTransform();
- return MGLStyleValueTransformer<mbgl::style::TextTransformType, NSValue *>().toStyleValue(propertyValue);
+- (MGLStyleValue<NSNumber *> *)textPadding {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextPadding() ?: _rawLayer->getDefaultTextPadding();
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setTextOffset:(MGLStyleValue<NSValue *> *)textOffset {
- auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(textOffset);
- self.layer->setTextOffset(mbglValue);
+- (void)setTextPitchAlignment:(MGLStyleValue<NSValue *> *)textPitchAlignment {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLTextPitchAlignment>().toEnumPropertyValue(textPitchAlignment);
+ _rawLayer->setTextPitchAlignment(mbglValue);
}
-- (MGLStyleValue<NSValue *> *)textOffset {
- auto propertyValue = self.layer->getTextOffset() ?: self.layer->getDefaultTextOffset();
- return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
+- (MGLStyleValue<NSValue *> *)textPitchAlignment {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextPitchAlignment() ?: _rawLayer->getDefaultTextPitchAlignment();
+ return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLTextPitchAlignment>().toEnumStyleValue(propertyValue);
}
-- (void)setTextAllowOverlap:(MGLStyleValue<NSNumber *> *)textAllowOverlap {
- auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(textAllowOverlap);
- self.layer->setTextAllowOverlap(mbglValue);
+- (void)setTextRotate:(MGLStyleValue<NSNumber *> *)textRotate {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textRotate);
+ _rawLayer->setTextRotate(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)textAllowOverlap {
- auto propertyValue = self.layer->getTextAllowOverlap() ?: self.layer->getDefaultTextAllowOverlap();
- return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
+- (MGLStyleValue<NSNumber *> *)textRotate {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextRotate() ?: _rawLayer->getDefaultTextRotate();
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setTextIgnorePlacement:(MGLStyleValue<NSNumber *> *)textIgnorePlacement {
- auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(textIgnorePlacement);
- self.layer->setTextIgnorePlacement(mbglValue);
+- (void)setTextRotationAlignment:(MGLStyleValue<NSValue *> *)textRotationAlignment {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLTextRotationAlignment>().toEnumPropertyValue(textRotationAlignment);
+ _rawLayer->setTextRotationAlignment(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)textIgnorePlacement {
- auto propertyValue = self.layer->getTextIgnorePlacement() ?: self.layer->getDefaultTextIgnorePlacement();
- return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
+- (MGLStyleValue<NSValue *> *)textRotationAlignment {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextRotationAlignment() ?: _rawLayer->getDefaultTextRotationAlignment();
+ return MGLStyleValueTransformer<mbgl::style::AlignmentType, NSValue *, mbgl::style::AlignmentType, MGLTextRotationAlignment>().toEnumStyleValue(propertyValue);
}
-- (void)setTextOptional:(MGLStyleValue<NSNumber *> *)textOptional {
- auto mbglValue = MGLStyleValueTransformer<bool, NSNumber *>().toPropertyValue(textOptional);
- self.layer->setTextOptional(mbglValue);
+- (void)setTextSize:(MGLStyleValue<NSNumber *> *)textSize {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textSize);
+ _rawLayer->setTextSize(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)textOptional {
- auto propertyValue = self.layer->getTextOptional() ?: self.layer->getDefaultTextOptional();
- return MGLStyleValueTransformer<bool, NSNumber *>().toStyleValue(propertyValue);
+- (MGLStyleValue<NSNumber *> *)textSize {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextSize() ?: _rawLayer->getDefaultTextSize();
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-#pragma mark - Accessing the Paint Attributes
+- (void)setTextTransform:(MGLStyleValue<NSValue *> *)textTransform {
+ MGLAssertStyleLayerIsValid();
-- (void)setIconOpacity:(MGLStyleValue<NSNumber *> *)iconOpacity {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconOpacity);
- self.layer->setIconOpacity(mbglValue);
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::TextTransformType, NSValue *, mbgl::style::TextTransformType, MGLTextTransform>().toEnumPropertyValue(textTransform);
+ _rawLayer->setTextTransform(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)iconOpacity {
- auto propertyValue = self.layer->getIconOpacity() ?: self.layer->getDefaultIconOpacity();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+- (MGLStyleValue<NSValue *> *)textTransform {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextTransform() ?: _rawLayer->getDefaultTextTransform();
+ return MGLStyleValueTransformer<mbgl::style::TextTransformType, NSValue *, mbgl::style::TextTransformType, MGLTextTransform>().toEnumStyleValue(propertyValue);
}
+#pragma mark - Accessing the Paint Attributes
+
- (void)setIconColor:(MGLStyleValue<MGLColor *> *)iconColor {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(iconColor);
- self.layer->setIconColor(mbglValue);
+ _rawLayer->setIconColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)iconColor {
- auto propertyValue = self.layer->getIconColor() ?: self.layer->getDefaultIconColor();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconColor() ?: _rawLayer->getDefaultIconColor();
return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
}
+- (void)setIconHaloBlur:(MGLStyleValue<NSNumber *> *)iconHaloBlur {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconHaloBlur);
+ _rawLayer->setIconHaloBlur(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)iconHaloBlur {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconHaloBlur() ?: _rawLayer->getDefaultIconHaloBlur();
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+}
+
- (void)setIconHaloColor:(MGLStyleValue<MGLColor *> *)iconHaloColor {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(iconHaloColor);
- self.layer->setIconHaloColor(mbglValue);
+ _rawLayer->setIconHaloColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)iconHaloColor {
- auto propertyValue = self.layer->getIconHaloColor() ?: self.layer->getDefaultIconHaloColor();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconHaloColor() ?: _rawLayer->getDefaultIconHaloColor();
return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
}
- (void)setIconHaloWidth:(MGLStyleValue<NSNumber *> *)iconHaloWidth {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconHaloWidth);
- self.layer->setIconHaloWidth(mbglValue);
+ _rawLayer->setIconHaloWidth(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)iconHaloWidth {
- auto propertyValue = self.layer->getIconHaloWidth() ?: self.layer->getDefaultIconHaloWidth();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconHaloWidth() ?: _rawLayer->getDefaultIconHaloWidth();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setIconHaloBlur:(MGLStyleValue<NSNumber *> *)iconHaloBlur {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconHaloBlur);
- self.layer->setIconHaloBlur(mbglValue);
+- (void)setIconOpacity:(MGLStyleValue<NSNumber *> *)iconOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(iconOpacity);
+ _rawLayer->setIconOpacity(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)iconHaloBlur {
- auto propertyValue = self.layer->getIconHaloBlur() ?: self.layer->getDefaultIconHaloBlur();
+- (MGLStyleValue<NSNumber *> *)iconOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconOpacity() ?: _rawLayer->getDefaultIconOpacity();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setIconTranslate:(MGLStyleValue<NSValue *> *)iconTranslate {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(iconTranslate);
- self.layer->setIconTranslate(mbglValue);
+ _rawLayer->setIconTranslate(mbglValue);
}
- (MGLStyleValue<NSValue *> *)iconTranslate {
- auto propertyValue = self.layer->getIconTranslate() ?: self.layer->getDefaultIconTranslate();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getIconTranslate() ?: _rawLayer->getDefaultIconTranslate();
return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
}
- (void)setIconTranslateAnchor:(MGLStyleValue<NSValue *> *)iconTranslateAnchor {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *>().toPropertyValue(iconTranslateAnchor);
- self.layer->setIconTranslateAnchor(mbglValue);
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLIconTranslateAnchor>().toEnumPropertyValue(iconTranslateAnchor);
+ _rawLayer->setIconTranslateAnchor(mbglValue);
}
- (MGLStyleValue<NSValue *> *)iconTranslateAnchor {
- auto propertyValue = self.layer->getIconTranslateAnchor() ?: self.layer->getDefaultIconTranslateAnchor();
- return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *>().toStyleValue(propertyValue);
-}
+ MGLAssertStyleLayerIsValid();
-- (void)setTextOpacity:(MGLStyleValue<NSNumber *> *)textOpacity {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textOpacity);
- self.layer->setTextOpacity(mbglValue);
-}
-
-- (MGLStyleValue<NSNumber *> *)textOpacity {
- auto propertyValue = self.layer->getTextOpacity() ?: self.layer->getDefaultTextOpacity();
- return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+ auto propertyValue = _rawLayer->getIconTranslateAnchor() ?: _rawLayer->getDefaultIconTranslateAnchor();
+ return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLIconTranslateAnchor>().toEnumStyleValue(propertyValue);
}
- (void)setTextColor:(MGLStyleValue<MGLColor *> *)textColor {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(textColor);
- self.layer->setTextColor(mbglValue);
+ _rawLayer->setTextColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)textColor {
- auto propertyValue = self.layer->getTextColor() ?: self.layer->getDefaultTextColor();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextColor() ?: _rawLayer->getDefaultTextColor();
return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
}
+- (void)setTextHaloBlur:(MGLStyleValue<NSNumber *> *)textHaloBlur {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textHaloBlur);
+ _rawLayer->setTextHaloBlur(mbglValue);
+}
+
+- (MGLStyleValue<NSNumber *> *)textHaloBlur {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextHaloBlur() ?: _rawLayer->getDefaultTextHaloBlur();
+ return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
+}
+
- (void)setTextHaloColor:(MGLStyleValue<MGLColor *> *)textHaloColor {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toPropertyValue(textHaloColor);
- self.layer->setTextHaloColor(mbglValue);
+ _rawLayer->setTextHaloColor(mbglValue);
}
- (MGLStyleValue<MGLColor *> *)textHaloColor {
- auto propertyValue = self.layer->getTextHaloColor() ?: self.layer->getDefaultTextHaloColor();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextHaloColor() ?: _rawLayer->getDefaultTextHaloColor();
return MGLStyleValueTransformer<mbgl::Color, MGLColor *>().toStyleValue(propertyValue);
}
- (void)setTextHaloWidth:(MGLStyleValue<NSNumber *> *)textHaloWidth {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textHaloWidth);
- self.layer->setTextHaloWidth(mbglValue);
+ _rawLayer->setTextHaloWidth(mbglValue);
}
- (MGLStyleValue<NSNumber *> *)textHaloWidth {
- auto propertyValue = self.layer->getTextHaloWidth() ?: self.layer->getDefaultTextHaloWidth();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextHaloWidth() ?: _rawLayer->getDefaultTextHaloWidth();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
-- (void)setTextHaloBlur:(MGLStyleValue<NSNumber *> *)textHaloBlur {
- auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textHaloBlur);
- self.layer->setTextHaloBlur(mbglValue);
+- (void)setTextOpacity:(MGLStyleValue<NSNumber *> *)textOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<float, NSNumber *>().toPropertyValue(textOpacity);
+ _rawLayer->setTextOpacity(mbglValue);
}
-- (MGLStyleValue<NSNumber *> *)textHaloBlur {
- auto propertyValue = self.layer->getTextHaloBlur() ?: self.layer->getDefaultTextHaloBlur();
+- (MGLStyleValue<NSNumber *> *)textOpacity {
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextOpacity() ?: _rawLayer->getDefaultTextOpacity();
return MGLStyleValueTransformer<float, NSNumber *>().toStyleValue(propertyValue);
}
- (void)setTextTranslate:(MGLStyleValue<NSValue *> *)textTranslate {
+ MGLAssertStyleLayerIsValid();
+
auto mbglValue = MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toPropertyValue(textTranslate);
- self.layer->setTextTranslate(mbglValue);
+ _rawLayer->setTextTranslate(mbglValue);
}
- (MGLStyleValue<NSValue *> *)textTranslate {
- auto propertyValue = self.layer->getTextTranslate() ?: self.layer->getDefaultTextTranslate();
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextTranslate() ?: _rawLayer->getDefaultTextTranslate();
return MGLStyleValueTransformer<std::array<float, 2>, NSValue *>().toStyleValue(propertyValue);
}
- (void)setTextTranslateAnchor:(MGLStyleValue<NSValue *> *)textTranslateAnchor {
- auto mbglValue = MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *>().toPropertyValue(textTranslateAnchor);
- self.layer->setTextTranslateAnchor(mbglValue);
+ MGLAssertStyleLayerIsValid();
+
+ auto mbglValue = MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLTextTranslateAnchor>().toEnumPropertyValue(textTranslateAnchor);
+ _rawLayer->setTextTranslateAnchor(mbglValue);
}
- (MGLStyleValue<NSValue *> *)textTranslateAnchor {
- auto propertyValue = self.layer->getTextTranslateAnchor() ?: self.layer->getDefaultTextTranslateAnchor();
- return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *>().toStyleValue(propertyValue);
+ MGLAssertStyleLayerIsValid();
+
+ auto propertyValue = _rawLayer->getTextTranslateAnchor() ?: _rawLayer->getDefaultTextTranslateAnchor();
+ return MGLStyleValueTransformer<mbgl::style::TranslateAnchorType, NSValue *, mbgl::style::TranslateAnchorType, MGLTextTranslateAnchor>().toEnumStyleValue(propertyValue);
}
+
@end
diff --git a/platform/darwin/src/MGLTileSet.mm b/platform/darwin/src/MGLTileSet.mm
index b2359bb92d..f795545eed 100644
--- a/platform/darwin/src/MGLTileSet.mm
+++ b/platform/darwin/src/MGLTileSet.mm
@@ -84,4 +84,10 @@
return tileset;
}
+- (NSString *)description
+{
+ return [NSString stringWithFormat:@"<%@: %p; tileURLTemplates = %@>",
+ NSStringFromClass([self class]), (void *)self, self.tileURLTemplates];
+}
+
@end
diff --git a/platform/darwin/src/MGLTypes.h b/platform/darwin/src/MGLTypes.h
index e9e05bc684..a6b7254b58 100644
--- a/platform/darwin/src/MGLTypes.h
+++ b/platform/darwin/src/MGLTypes.h
@@ -20,6 +20,13 @@
NS_ASSUME_NONNULL_BEGIN
+#ifndef NS_STRING_ENUM
+ #define NS_STRING_ENUM
+ #define NS_EXTENSIBLE_STRING_ENUM
+ typedef NSString *NSErrorDomain;
+ typedef NSString *NSNotificationName;
+#endif
+
/** Indicates an error occurred in the Mapbox SDK. */
extern NSErrorDomain const MGLErrorDomain;
@@ -97,9 +104,3 @@ NS_ASSUME_NONNULL_END
#define NS_MUTABLE_DICTIONARY_OF(ObjectClass...) NSMutableDictionary
#endif
#endif
-
-#if !defined(FOUNDATION_SWIFT_SDK_EPOCH_LESS_THAN) || FOUNDATION_SWIFT_SDK_EPOCH_LESS_THAN(8)
- #define NS_STRING_ENUM
- #define NS_EXTENSIBLE_STRING_ENUM
- #define NSNotificationName NSString *
-#endif
diff --git a/platform/darwin/src/MGLVectorSource.mm b/platform/darwin/src/MGLVectorSource.mm
index 995565419f..ab68d45ba1 100644
--- a/platform/darwin/src/MGLVectorSource.mm
+++ b/platform/darwin/src/MGLVectorSource.mm
@@ -18,8 +18,6 @@
std::unique_ptr<mbgl::style::VectorSource> _pendingSource;
}
-static NSString *MGLVectorSourceType = @"vector";
-
- (instancetype)initWithIdentifier:(NSString *)identifier URL:(NSURL *)url
{
if (self = [super initWithIdentifier:identifier])
@@ -61,7 +59,27 @@ static NSString *MGLVectorSourceType = @"vector";
- (void)addToMapView:(MGLMapView *)mapView
{
+ if (_pendingSource == nullptr) {
+ [NSException raise:@"MGLRedundantSourceException"
+ format:@"This instance %@ was already added to %@. Adding the same source instance " \
+ "to the style more than once is invalid.", self, mapView.style];
+ }
+
mapView.mbglMap->addSource(std::move(_pendingSource));
}
+- (void)removeFromMapView:(MGLMapView *)mapView
+{
+ auto removedSource = mapView.mbglMap->removeSource(self.identifier.UTF8String);
+
+ _pendingSource = std::move(reinterpret_cast<std::unique_ptr<mbgl::style::VectorSource> &>(removedSource));
+ self.rawSource = _pendingSource.get();
+}
+
+- (NSString *)description
+{
+ return [NSString stringWithFormat:@"<%@: %p; identifier = %@; URL = %@; tileSet = %@>",
+ NSStringFromClass([self class]), (void *)self, self.identifier, self.URL, self.tileSet];
+}
+
@end
diff --git a/platform/darwin/src/MGLVectorStyleLayer.h b/platform/darwin/src/MGLVectorStyleLayer.h
index 13bb9e79a9..e2a755083f 100644
--- a/platform/darwin/src/MGLVectorStyleLayer.h
+++ b/platform/darwin/src/MGLVectorStyleLayer.h
@@ -52,10 +52,11 @@ NS_ASSUME_NONNULL_BEGIN
<li><code>NSNotPredicateType</code> (<code>NOT</code>, <code>!</code>)</li>
</ul>
- The following aggregate operator is supported:
+ The following aggregate operators are supported:
<ul>
<li><code>NSInPredicateOperatorType</code> (<code>IN</code>)</li>
+ <li><code>NSContainsPredicateOperatorType</code> (<code>CONTAINS</code>)</li>
</ul>
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.
@@ -118,7 +119,9 @@ NS_ASSUME_NONNULL_BEGIN
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.
+ value specified in the predicate. Also, operator modifiers `c`, `d`, and the
+ combined `cd` for case and diacritic insensitivity are unsupported for
+ comparison and aggregate operators that are used in the predicate.
*/
@property (nonatomic, nullable) NSPredicate *predicate;
diff --git a/platform/darwin/src/MGLVectorStyleLayer.m b/platform/darwin/src/MGLVectorStyleLayer.m
index 174256cbdd..d8146f4246 100644
--- a/platform/darwin/src/MGLVectorStyleLayer.m
+++ b/platform/darwin/src/MGLVectorStyleLayer.m
@@ -13,4 +13,13 @@
return nil;
}
+- (NSString *)description {
+ return [NSString stringWithFormat:
+ @"<%@: %p; identifier = %@; sourceIdentifier = %@; "
+ @"sourceLayerIdentifier = %@; predicate = %@; visible = %@>",
+ NSStringFromClass([self class]), (void *)self, self.identifier,
+ self.sourceIdentifier, self.sourceLayerIdentifier, self.predicate,
+ self.visible ? @"YES" : @"NO"];
+}
+
@end
diff --git a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm
index aa0e456bb1..19c264aa40 100644
--- a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm
+++ b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm
@@ -68,6 +68,12 @@
filter.values = self.rightExpression.mgl_filterValues;
return filter;
}
+ case NSContainsPredicateOperatorType: {
+ auto filter = mbgl::style::InFilter();
+ filter.key = [self.rightExpression.constantValue UTF8String];
+ filter.values = self.leftExpression.mgl_filterValues;
+ return filter;
+ }
case NSBetweenPredicateOperatorType: {
auto filter = mbgl::style::AllFilter();
auto gteFilter = mbgl::style::GreaterThanEqualsFilter();
@@ -85,7 +91,6 @@
case NSBeginsWithPredicateOperatorType:
case NSEndsWithPredicateOperatorType:
case NSCustomSelectorPredicateOperatorType:
- case NSContainsPredicateOperatorType:
[NSException raise:@"Unsupported operator type"
format:@"NSPredicateOperatorType:%lu is not supported.", (unsigned long)self.predicateOperatorType];
}
diff --git a/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h b/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h
new file mode 100644
index 0000000000..8aa07b2a0c
--- /dev/null
+++ b/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h
@@ -0,0 +1,232 @@
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+
+#import <Foundation/Foundation.h>
+
+#import "MGLFillStyleLayer.h"
+#import "MGLLineStyleLayer.h"
+#import "MGLSymbolStyleLayer.h"
+#import "MGLCircleStyleLayer.h"
+#import "MGLRasterStyleLayer.h"
+#import "MGLBackgroundStyleLayer.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ Methods for round-tripping values for Mapbox style layer enumeration values.
+*/
+@interface NSValue (MGLStyleEnumAttributeAdditions)
+
+#pragma mark Working with Style Layer Enumeration Attribute Values
+
+/**
+ Creates a new value object containing the given `MGLLineCap` enumeration.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLLineCap:(MGLLineCap)lineCap;
+
+/**
+ The `MGLLineCap` enumeration representation of the value.
+*/
+@property (readonly) MGLLineCap MGLLineCapValue;
+
+/**
+ Creates a new value object containing the given `MGLLineJoin` enumeration.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLLineJoin:(MGLLineJoin)lineJoin;
+
+/**
+ The `MGLLineJoin` enumeration representation of the value.
+*/
+@property (readonly) MGLLineJoin MGLLineJoinValue;
+
+/**
+ Creates a new value object containing the given `MGLIconRotationAlignment` enumeration.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLIconRotationAlignment:(MGLIconRotationAlignment)iconRotationAlignment;
+
+/**
+ The `MGLIconRotationAlignment` enumeration representation of the value.
+*/
+@property (readonly) MGLIconRotationAlignment MGLIconRotationAlignmentValue;
+
+/**
+ Creates a new value object containing the given `MGLIconTextFit` enumeration.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLIconTextFit:(MGLIconTextFit)iconTextFit;
+
+/**
+ The `MGLIconTextFit` enumeration representation of the value.
+*/
+@property (readonly) MGLIconTextFit MGLIconTextFitValue;
+
+/**
+ Creates a new value object containing the given `MGLSymbolPlacement` enumeration.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLSymbolPlacement:(MGLSymbolPlacement)symbolPlacement;
+
+/**
+ The `MGLSymbolPlacement` enumeration representation of the value.
+*/
+@property (readonly) MGLSymbolPlacement MGLSymbolPlacementValue;
+
+/**
+ Creates a new value object containing the given `MGLTextAnchor` enumeration.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLTextAnchor:(MGLTextAnchor)textAnchor;
+
+/**
+ The `MGLTextAnchor` enumeration representation of the value.
+*/
+@property (readonly) MGLTextAnchor MGLTextAnchorValue;
+
+/**
+ Creates a new value object containing the given `MGLTextJustify` enumeration.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLTextJustify:(MGLTextJustify)textJustify;
+
+/**
+ The `MGLTextJustify` enumeration representation of the value.
+*/
+@property (readonly) MGLTextJustify MGLTextJustifyValue;
+
+/**
+ Creates a new value object containing the given `MGLTextPitchAlignment` enumeration.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLTextPitchAlignment:(MGLTextPitchAlignment)textPitchAlignment;
+
+/**
+ The `MGLTextPitchAlignment` enumeration representation of the value.
+*/
+@property (readonly) MGLTextPitchAlignment MGLTextPitchAlignmentValue;
+
+/**
+ Creates a new value object containing the given `MGLTextRotationAlignment` enumeration.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLTextRotationAlignment:(MGLTextRotationAlignment)textRotationAlignment;
+
+/**
+ The `MGLTextRotationAlignment` enumeration representation of the value.
+*/
+@property (readonly) MGLTextRotationAlignment MGLTextRotationAlignmentValue;
+
+/**
+ Creates a new value object containing the given `MGLTextTransform` enumeration.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLTextTransform:(MGLTextTransform)textTransform;
+
+/**
+ The `MGLTextTransform` enumeration representation of the value.
+*/
+@property (readonly) MGLTextTransform MGLTextTransformValue;
+
+/**
+ Creates a new value object containing the given `MGLFillTranslateAnchor` structure.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLFillTranslateAnchor:(MGLFillTranslateAnchor)fillTranslateAnchor;
+
+/**
+ The `MGLFillTranslateAnchor` enumeration representation of the value.
+*/
+@property (readonly) MGLFillTranslateAnchor MGLFillTranslateAnchorValue;
+
+/**
+ Creates a new value object containing the given `MGLLineTranslateAnchor` structure.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLLineTranslateAnchor:(MGLLineTranslateAnchor)lineTranslateAnchor;
+
+/**
+ The `MGLLineTranslateAnchor` enumeration representation of the value.
+*/
+@property (readonly) MGLLineTranslateAnchor MGLLineTranslateAnchorValue;
+
+/**
+ Creates a new value object containing the given `MGLIconTranslateAnchor` structure.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLIconTranslateAnchor:(MGLIconTranslateAnchor)iconTranslateAnchor;
+
+/**
+ The `MGLIconTranslateAnchor` enumeration representation of the value.
+*/
+@property (readonly) MGLIconTranslateAnchor MGLIconTranslateAnchorValue;
+
+/**
+ Creates a new value object containing the given `MGLTextTranslateAnchor` structure.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLTextTranslateAnchor:(MGLTextTranslateAnchor)textTranslateAnchor;
+
+/**
+ The `MGLTextTranslateAnchor` enumeration representation of the value.
+*/
+@property (readonly) MGLTextTranslateAnchor MGLTextTranslateAnchorValue;
+
+/**
+ Creates a new value object containing the given `MGLCirclePitchScale` structure.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLCirclePitchScale:(MGLCirclePitchScale)circlePitchScale;
+
+/**
+ The `MGLCirclePitchScale` enumeration representation of the value.
+*/
+@property (readonly) MGLCirclePitchScale MGLCirclePitchScaleValue;
+
+/**
+ Creates a new value object containing the given `MGLCircleTranslateAnchor` structure.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGLCircleTranslateAnchor:(MGLCircleTranslateAnchor)circleTranslateAnchor;
+
+/**
+ The `MGLCircleTranslateAnchor` enumeration representation of the value.
+*/
+@property (readonly) MGLCircleTranslateAnchor MGLCircleTranslateAnchorValue;
+
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h.ejs b/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h.ejs
new file mode 100644
index 0000000000..c078ac7d02
--- /dev/null
+++ b/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.h.ejs
@@ -0,0 +1,66 @@
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+
+<%
+const types = locals.types;
+const layoutProperties = locals.layoutProperties;
+const paintProperties = locals.paintProperties;
+-%>
+#import <Foundation/Foundation.h>
+
+<% if (types) { -%>
+<% for (const type of types) { -%>
+#import "MGL<%- camelize(type) %>StyleLayer.h"
+<% } -%>
+<% } -%>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/**
+ Methods for round-tripping values for Mapbox style layer enumeration values.
+*/
+@interface NSValue (MGLStyleEnumAttributeAdditions)
+
+#pragma mark Working with Style Layer Enumeration Attribute Values
+
+<% if (layoutProperties.length) { -%>
+<% for (const property of layoutProperties) { -%>
+<% if (property.type == "enum") { -%>
+/**
+ Creates a new value object containing the given `MGL<%- camelize(property.name) %>` enumeration.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGL<%- camelize(property.name) %>:(MGL<%- camelize(property.name) %>)<%- objCName(property) %>;
+
+/**
+ The `MGL<%- camelize(property.name) %>` enumeration representation of the value.
+*/
+@property (readonly) MGL<%- camelize(property.name) %> MGL<%- camelize(property.name) %>Value;
+
+<% } -%>
+<% } -%>
+<% } -%>
+<% if (paintProperties.length) { -%>
+<% for (const property of paintProperties) { -%>
+<% if (property.type == "enum") { -%>
+/**
+ Creates a new value object containing the given `MGL<%- camelize(property.name) %>` structure.
+
+ @param type The value for the new object.
+ @return A new value object that contains the style enumeration type.
+*/
++ (instancetype)valueWithMGL<%- camelize(property.name) %>:(MGL<%- camelize(property.name) %>)<%- objCName(property) %>;
+
+/**
+ The `MGL<%- camelize(property.name) %>` enumeration representation of the value.
+*/
+@property (readonly) MGL<%- camelize(property.name) %> MGL<%- camelize(property.name) %>Value;
+
+<% } -%>
+<% } -%>
+<% } -%>
+@end
+
+NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm b/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm
new file mode 100644
index 0000000000..89f0c07a5a
--- /dev/null
+++ b/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm
@@ -0,0 +1,169 @@
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+
+#import "NSValue+MGLStyleEnumAttributeAdditions.h"
+
+@implementation NSValue (MGLStyleEnumAttributeAdditions)
+
++ (NSValue *)valueWithMGLLineCap:(MGLLineCap)lineCap {
+ return [NSValue value:&lineCap withObjCType:@encode(MGLLineCap)];
+}
+
+- (MGLLineCap)MGLLineCapValue {
+ MGLLineCap value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLLineJoin:(MGLLineJoin)lineJoin {
+ return [NSValue value:&lineJoin withObjCType:@encode(MGLLineJoin)];
+}
+
+- (MGLLineJoin)MGLLineJoinValue {
+ MGLLineJoin value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLIconRotationAlignment:(MGLIconRotationAlignment)iconRotationAlignment {
+ return [NSValue value:&iconRotationAlignment withObjCType:@encode(MGLIconRotationAlignment)];
+}
+
+- (MGLIconRotationAlignment)MGLIconRotationAlignmentValue {
+ MGLIconRotationAlignment value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLIconTextFit:(MGLIconTextFit)iconTextFit {
+ return [NSValue value:&iconTextFit withObjCType:@encode(MGLIconTextFit)];
+}
+
+- (MGLIconTextFit)MGLIconTextFitValue {
+ MGLIconTextFit value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLSymbolPlacement:(MGLSymbolPlacement)symbolPlacement {
+ return [NSValue value:&symbolPlacement withObjCType:@encode(MGLSymbolPlacement)];
+}
+
+- (MGLSymbolPlacement)MGLSymbolPlacementValue {
+ MGLSymbolPlacement value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLTextAnchor:(MGLTextAnchor)textAnchor {
+ return [NSValue value:&textAnchor withObjCType:@encode(MGLTextAnchor)];
+}
+
+- (MGLTextAnchor)MGLTextAnchorValue {
+ MGLTextAnchor value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLTextJustify:(MGLTextJustify)textJustify {
+ return [NSValue value:&textJustify withObjCType:@encode(MGLTextJustify)];
+}
+
+- (MGLTextJustify)MGLTextJustifyValue {
+ MGLTextJustify value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLTextPitchAlignment:(MGLTextPitchAlignment)textPitchAlignment {
+ return [NSValue value:&textPitchAlignment withObjCType:@encode(MGLTextPitchAlignment)];
+}
+
+- (MGLTextPitchAlignment)MGLTextPitchAlignmentValue {
+ MGLTextPitchAlignment value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLTextRotationAlignment:(MGLTextRotationAlignment)textRotationAlignment {
+ return [NSValue value:&textRotationAlignment withObjCType:@encode(MGLTextRotationAlignment)];
+}
+
+- (MGLTextRotationAlignment)MGLTextRotationAlignmentValue {
+ MGLTextRotationAlignment value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLTextTransform:(MGLTextTransform)textTransform {
+ return [NSValue value:&textTransform withObjCType:@encode(MGLTextTransform)];
+}
+
+- (MGLTextTransform)MGLTextTransformValue {
+ MGLTextTransform value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLFillTranslateAnchor:(MGLFillTranslateAnchor)fillTranslateAnchor {
+return [NSValue value:&fillTranslateAnchor withObjCType:@encode(MGLFillTranslateAnchor)];
+}
+
+- (MGLFillTranslateAnchor)MGLFillTranslateAnchorValue {
+ MGLFillTranslateAnchor value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLLineTranslateAnchor:(MGLLineTranslateAnchor)lineTranslateAnchor {
+return [NSValue value:&lineTranslateAnchor withObjCType:@encode(MGLLineTranslateAnchor)];
+}
+
+- (MGLLineTranslateAnchor)MGLLineTranslateAnchorValue {
+ MGLLineTranslateAnchor value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLIconTranslateAnchor:(MGLIconTranslateAnchor)iconTranslateAnchor {
+return [NSValue value:&iconTranslateAnchor withObjCType:@encode(MGLIconTranslateAnchor)];
+}
+
+- (MGLIconTranslateAnchor)MGLIconTranslateAnchorValue {
+ MGLIconTranslateAnchor value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLTextTranslateAnchor:(MGLTextTranslateAnchor)textTranslateAnchor {
+return [NSValue value:&textTranslateAnchor withObjCType:@encode(MGLTextTranslateAnchor)];
+}
+
+- (MGLTextTranslateAnchor)MGLTextTranslateAnchorValue {
+ MGLTextTranslateAnchor value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLCirclePitchScale:(MGLCirclePitchScale)circlePitchScale {
+return [NSValue value:&circlePitchScale withObjCType:@encode(MGLCirclePitchScale)];
+}
+
+- (MGLCirclePitchScale)MGLCirclePitchScaleValue {
+ MGLCirclePitchScale value;
+ [self getValue:&value];
+ return value;
+}
+
++ (NSValue *)valueWithMGLCircleTranslateAnchor:(MGLCircleTranslateAnchor)circleTranslateAnchor {
+return [NSValue value:&circleTranslateAnchor withObjCType:@encode(MGLCircleTranslateAnchor)];
+}
+
+- (MGLCircleTranslateAnchor)MGLCircleTranslateAnchorValue {
+ MGLCircleTranslateAnchor value;
+ [self getValue:&value];
+ return value;
+}
+
+
+@end
diff --git a/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm.ejs b/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm.ejs
new file mode 100644
index 0000000000..fab278aac8
--- /dev/null
+++ b/platform/darwin/src/NSValue+MGLStyleEnumAttributeAdditions.mm.ejs
@@ -0,0 +1,46 @@
+// This file is generated.
+// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
+<%
+const type = locals.type;
+const layoutProperties = locals.layoutProperties;
+const paintProperties = locals.paintProperties;
+-%>
+
+#import "NSValue+MGLStyleEnumAttributeAdditions.h"
+
+@implementation NSValue (MGLStyleEnumAttributeAdditions)
+
+<% if (layoutProperties.length) { -%>
+<% for (const property of layoutProperties) { -%>
+<% if (property.type == "enum") { -%>
++ (NSValue *)valueWithMGL<%- camelize(property.name) %>:(MGL<%- camelize(property.name) %>)<%- objCName(property) %> {
+ return [NSValue value:&<%- objCName(property) %> withObjCType:@encode(MGL<%- camelize(property.name) %>)];
+}
+
+- (MGL<%- camelize(property.name) %>)MGL<%- camelize(property.name) %>Value {
+ MGL<%- camelize(property.name) %> value;
+ [self getValue:&value];
+ return value;
+}
+
+<% } -%>
+<% } -%>
+<% } -%>
+<% if (paintProperties.length) { -%>
+<% for (const property of paintProperties) { -%>
+<% if (property.type == "enum") { -%>
++ (NSValue *)valueWithMGL<%- camelize(property.name) %>:(MGL<%- camelize(property.name) %>)<%- objCName(property) %> {
+return [NSValue value:&<%- objCName(property) %> withObjCType:@encode(MGL<%- camelize(property.name) %>)];
+}
+
+- (MGL<%- camelize(property.name) %>)MGL<%- camelize(property.name) %>Value {
+ MGL<%- camelize(property.name) %> value;
+ [self getValue:&value];
+ return value;
+}
+
+<% } -%>
+<% } -%>
+<% } -%>
+
+@end
diff --git a/platform/darwin/test/MGLBackgroundStyleLayerTests.m b/platform/darwin/test/MGLBackgroundStyleLayerTests.m
index 75181cdf0c..09bed76654 100644
--- a/platform/darwin/test/MGLBackgroundStyleLayerTests.m
+++ b/platform/darwin/test/MGLBackgroundStyleLayerTests.m
@@ -1,9 +1,9 @@
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
-#import "MGLMapViewTests.h"
+#import "MGLStyleLayerTests.h"
-@interface MGLBackgroundLayerTests : MGLMapViewTests
+@interface MGLBackgroundLayerTests : MGLStyleLayerTests
@end
@implementation MGLBackgroundLayerTests
@@ -13,22 +13,22 @@
[self.mapView.style addLayer:layer];
layer.backgroundColor = [MGLRuntimeStylingHelper testColor];
- layer.backgroundPattern = [MGLRuntimeStylingHelper testString];
layer.backgroundOpacity = [MGLRuntimeStylingHelper testNumber];
+ layer.backgroundPattern = [MGLRuntimeStylingHelper testString];
MGLBackgroundStyleLayer *gLayer = (MGLBackgroundStyleLayer *)[self.mapView.style layerWithIdentifier:@"layerID"];
XCTAssertTrue([gLayer isKindOfClass:[MGLBackgroundStyleLayer class]]);
XCTAssertEqualObjects(gLayer.backgroundColor, [MGLRuntimeStylingHelper testColor]);
- XCTAssertEqualObjects(gLayer.backgroundPattern, [MGLRuntimeStylingHelper testString]);
XCTAssertEqualObjects(gLayer.backgroundOpacity, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.backgroundPattern, [MGLRuntimeStylingHelper testString]);
layer.backgroundColor = [MGLRuntimeStylingHelper testColorFunction];
- layer.backgroundPattern = [MGLRuntimeStylingHelper testStringFunction];
layer.backgroundOpacity = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.backgroundPattern = [MGLRuntimeStylingHelper testStringFunction];
XCTAssertEqualObjects(gLayer.backgroundColor, [MGLRuntimeStylingHelper testColorFunction]);
- XCTAssertEqualObjects(gLayer.backgroundPattern, [MGLRuntimeStylingHelper testStringFunction]);
XCTAssertEqualObjects(gLayer.backgroundOpacity, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.backgroundPattern, [MGLRuntimeStylingHelper testStringFunction]);
}
@end
diff --git a/platform/darwin/test/MGLCircleStyleLayerTests.m b/platform/darwin/test/MGLCircleStyleLayerTests.m
index eb175de621..432d3ffa79 100644
--- a/platform/darwin/test/MGLCircleStyleLayerTests.m
+++ b/platform/darwin/test/MGLCircleStyleLayerTests.m
@@ -1,9 +1,9 @@
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
-#import "MGLMapViewTests.h"
+#import "MGLStyleLayerTests.h"
-@interface MGLCircleLayerTests : MGLMapViewTests
+@interface MGLCircleLayerTests : MGLStyleLayerTests
@end
@implementation MGLCircleLayerTests
@@ -16,41 +16,41 @@
MGLCircleStyleLayer *layer = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
[self.mapView.style addLayer:layer];
- layer.circleRadius = [MGLRuntimeStylingHelper testNumber];
- layer.circleColor = [MGLRuntimeStylingHelper testColor];
layer.circleBlur = [MGLRuntimeStylingHelper testNumber];
+ layer.circleColor = [MGLRuntimeStylingHelper testColor];
layer.circleOpacity = [MGLRuntimeStylingHelper testNumber];
+ layer.circlePitchScale = [MGLRuntimeStylingHelper testEnum:MGLCirclePitchScaleViewport type:@encode(MGLCirclePitchScale)];
+ layer.circleRadius = [MGLRuntimeStylingHelper testNumber];
layer.circleTranslate = [MGLRuntimeStylingHelper testOffset];
layer.circleTranslateAnchor = [MGLRuntimeStylingHelper testEnum:MGLCircleTranslateAnchorViewport type:@encode(MGLCircleTranslateAnchor)];
- layer.circlePitchScale = [MGLRuntimeStylingHelper testEnum:MGLCirclePitchScaleViewport type:@encode(MGLCirclePitchScale)];
MGLCircleStyleLayer *gLayer = (MGLCircleStyleLayer *)[self.mapView.style layerWithIdentifier:@"layerID"];
XCTAssertTrue([gLayer isKindOfClass:[MGLCircleStyleLayer class]]);
- XCTAssertEqualObjects(gLayer.circleRadius, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.circleColor, [MGLRuntimeStylingHelper testColor]);
XCTAssertEqualObjects(gLayer.circleBlur, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.circleColor, [MGLRuntimeStylingHelper testColor]);
XCTAssertEqualObjects(gLayer.circleOpacity, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssert([gLayer.circlePitchScale isKindOfClass:[MGLStyleConstantValue class]]);
+ XCTAssertEqualObjects(gLayer.circlePitchScale, [MGLRuntimeStylingHelper testEnum:MGLCirclePitchScaleViewport type:@encode(MGLCirclePitchScale)]);
+ XCTAssertEqualObjects(gLayer.circleRadius, [MGLRuntimeStylingHelper testNumber]);
XCTAssertEqualObjects(gLayer.circleTranslate, [MGLRuntimeStylingHelper testOffset]);
XCTAssert([gLayer.circleTranslateAnchor isKindOfClass:[MGLStyleConstantValue class]]);
XCTAssertEqualObjects(gLayer.circleTranslateAnchor, [MGLRuntimeStylingHelper testEnum:MGLCircleTranslateAnchorViewport type:@encode(MGLCircleTranslateAnchor)]);
- XCTAssert([gLayer.circlePitchScale isKindOfClass:[MGLStyleConstantValue class]]);
- XCTAssertEqualObjects(gLayer.circlePitchScale, [MGLRuntimeStylingHelper testEnum:MGLCirclePitchScaleViewport type:@encode(MGLCirclePitchScale)]);
- layer.circleRadius = [MGLRuntimeStylingHelper testNumberFunction];
- layer.circleColor = [MGLRuntimeStylingHelper testColorFunction];
layer.circleBlur = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.circleColor = [MGLRuntimeStylingHelper testColorFunction];
layer.circleOpacity = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.circlePitchScale = [MGLRuntimeStylingHelper testEnumFunction:MGLCirclePitchScaleViewport type:@encode(MGLCirclePitchScale)];
+ layer.circleRadius = [MGLRuntimeStylingHelper testNumberFunction];
layer.circleTranslate = [MGLRuntimeStylingHelper testOffsetFunction];
layer.circleTranslateAnchor = [MGLRuntimeStylingHelper testEnumFunction:MGLCircleTranslateAnchorViewport type:@encode(MGLCircleTranslateAnchor)];
- layer.circlePitchScale = [MGLRuntimeStylingHelper testEnumFunction:MGLCirclePitchScaleViewport type:@encode(MGLCirclePitchScale)];
- XCTAssertEqualObjects(gLayer.circleRadius, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.circleColor, [MGLRuntimeStylingHelper testColorFunction]);
XCTAssertEqualObjects(gLayer.circleBlur, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.circleColor, [MGLRuntimeStylingHelper testColorFunction]);
XCTAssertEqualObjects(gLayer.circleOpacity, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.circlePitchScale, [MGLRuntimeStylingHelper testEnumFunction:MGLCirclePitchScaleViewport type:@encode(MGLCirclePitchScale)]);
+ XCTAssertEqualObjects(gLayer.circleRadius, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.circleTranslate, [MGLRuntimeStylingHelper testOffsetFunction]);
XCTAssertEqualObjects(gLayer.circleTranslateAnchor, [MGLRuntimeStylingHelper testEnumFunction:MGLCircleTranslateAnchorViewport type:@encode(MGLCircleTranslateAnchor)]);
- XCTAssertEqualObjects(gLayer.circlePitchScale, [MGLRuntimeStylingHelper testEnumFunction:MGLCirclePitchScaleViewport type:@encode(MGLCirclePitchScale)]);
}
@end
diff --git a/platform/darwin/test/MGLFillStyleLayerTests.m b/platform/darwin/test/MGLFillStyleLayerTests.m
index ca8015ecfd..87846302ea 100644
--- a/platform/darwin/test/MGLFillStyleLayerTests.m
+++ b/platform/darwin/test/MGLFillStyleLayerTests.m
@@ -1,9 +1,9 @@
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
-#import "MGLMapViewTests.h"
+#import "MGLStyleLayerTests.h"
-@interface MGLFillLayerTests : MGLMapViewTests
+@interface MGLFillLayerTests : MGLStyleLayerTests
@end
@implementation MGLFillLayerTests
@@ -17,39 +17,39 @@
[self.mapView.style addLayer:layer];
layer.fillAntialias = [MGLRuntimeStylingHelper testBool];
- layer.fillOpacity = [MGLRuntimeStylingHelper testNumber];
layer.fillColor = [MGLRuntimeStylingHelper testColor];
+ layer.fillOpacity = [MGLRuntimeStylingHelper testNumber];
layer.fillOutlineColor = [MGLRuntimeStylingHelper testColor];
+ layer.fillPattern = [MGLRuntimeStylingHelper testString];
layer.fillTranslate = [MGLRuntimeStylingHelper testOffset];
layer.fillTranslateAnchor = [MGLRuntimeStylingHelper testEnum:MGLFillTranslateAnchorViewport type:@encode(MGLFillTranslateAnchor)];
- layer.fillPattern = [MGLRuntimeStylingHelper testString];
MGLFillStyleLayer *gLayer = (MGLFillStyleLayer *)[self.mapView.style layerWithIdentifier:@"layerID"];
XCTAssertTrue([gLayer isKindOfClass:[MGLFillStyleLayer class]]);
XCTAssertEqualObjects(gLayer.fillAntialias, [MGLRuntimeStylingHelper testBool]);
- XCTAssertEqualObjects(gLayer.fillOpacity, [MGLRuntimeStylingHelper testNumber]);
XCTAssertEqualObjects(gLayer.fillColor, [MGLRuntimeStylingHelper testColor]);
+ XCTAssertEqualObjects(gLayer.fillOpacity, [MGLRuntimeStylingHelper testNumber]);
XCTAssertEqualObjects(gLayer.fillOutlineColor, [MGLRuntimeStylingHelper testColor]);
+ XCTAssertEqualObjects(gLayer.fillPattern, [MGLRuntimeStylingHelper testString]);
XCTAssertEqualObjects(gLayer.fillTranslate, [MGLRuntimeStylingHelper testOffset]);
XCTAssert([gLayer.fillTranslateAnchor isKindOfClass:[MGLStyleConstantValue class]]);
XCTAssertEqualObjects(gLayer.fillTranslateAnchor, [MGLRuntimeStylingHelper testEnum:MGLFillTranslateAnchorViewport type:@encode(MGLFillTranslateAnchor)]);
- XCTAssertEqualObjects(gLayer.fillPattern, [MGLRuntimeStylingHelper testString]);
layer.fillAntialias = [MGLRuntimeStylingHelper testBoolFunction];
- layer.fillOpacity = [MGLRuntimeStylingHelper testNumberFunction];
layer.fillColor = [MGLRuntimeStylingHelper testColorFunction];
+ layer.fillOpacity = [MGLRuntimeStylingHelper testNumberFunction];
layer.fillOutlineColor = [MGLRuntimeStylingHelper testColorFunction];
+ layer.fillPattern = [MGLRuntimeStylingHelper testStringFunction];
layer.fillTranslate = [MGLRuntimeStylingHelper testOffsetFunction];
layer.fillTranslateAnchor = [MGLRuntimeStylingHelper testEnumFunction:MGLFillTranslateAnchorViewport type:@encode(MGLFillTranslateAnchor)];
- layer.fillPattern = [MGLRuntimeStylingHelper testStringFunction];
XCTAssertEqualObjects(gLayer.fillAntialias, [MGLRuntimeStylingHelper testBoolFunction]);
- XCTAssertEqualObjects(gLayer.fillOpacity, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.fillColor, [MGLRuntimeStylingHelper testColorFunction]);
+ XCTAssertEqualObjects(gLayer.fillOpacity, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.fillOutlineColor, [MGLRuntimeStylingHelper testColorFunction]);
+ XCTAssertEqualObjects(gLayer.fillPattern, [MGLRuntimeStylingHelper testStringFunction]);
XCTAssertEqualObjects(gLayer.fillTranslate, [MGLRuntimeStylingHelper testOffsetFunction]);
XCTAssertEqualObjects(gLayer.fillTranslateAnchor, [MGLRuntimeStylingHelper testEnumFunction:MGLFillTranslateAnchorViewport type:@encode(MGLFillTranslateAnchor)]);
- XCTAssertEqualObjects(gLayer.fillPattern, [MGLRuntimeStylingHelper testStringFunction]);
}
@end
diff --git a/platform/darwin/test/MGLFilterTests.mm b/platform/darwin/test/MGLFilterTests.mm
index 72927df0a1..b18400f83a 100644
--- a/platform/darwin/test/MGLFilterTests.mm
+++ b/platform/darwin/test/MGLFilterTests.mm
@@ -1,10 +1,10 @@
-#import "MGLMapViewTests.h"
+#import "MGLStyleLayerTests.h"
#import "NSPredicate+MGLAdditions.h"
#import "MGLValueEvaluator.h"
-@interface MGLFilterTests : MGLMapViewTests {
+@interface MGLFilterTests : MGLStyleLayerTests {
MGLGeoJSONSource *source;
MGLLineStyleLayer *layer;
}
@@ -74,6 +74,18 @@
[self.mapView.style addLayer:layer];
}
+- (void)testContainsPredicate
+{
+ // core does not have a "contains" filter but we can achieve the equivalent by creating an `mbgl::style::InFilter`
+ // and searching the value for the key
+ NSPredicate *expectedPredicate = [NSPredicate predicateWithFormat:@"park IN %@", @[@"park", @"neighbourhood"]];
+ NSPredicate *containsPredicate = [NSPredicate predicateWithFormat:@"%@ CONTAINS %@", @[@"park", @"neighbourhood"], @"park"];
+
+ layer.predicate = containsPredicate;
+ XCTAssertEqualObjects(layer.predicate, expectedPredicate);
+ [self.mapView.style addLayer:layer];
+}
+
- (void)testBetweenPredicate
{
// core does not have a "between" filter but we can achieve the equivalent by creating a set of greater than or equal / less than or equal
diff --git a/platform/darwin/test/MGLLineStyleLayerTests.m b/platform/darwin/test/MGLLineStyleLayerTests.m
index d368451562..95983b1f52 100644
--- a/platform/darwin/test/MGLLineStyleLayerTests.m
+++ b/platform/darwin/test/MGLLineStyleLayerTests.m
@@ -1,9 +1,9 @@
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
-#import "MGLMapViewTests.h"
+#import "MGLStyleLayerTests.h"
-@interface MGLLineLayerTests : MGLMapViewTests
+@interface MGLLineLayerTests : MGLStyleLayerTests
@end
@implementation MGLLineLayerTests
@@ -20,16 +20,16 @@
layer.lineJoin = [MGLRuntimeStylingHelper testEnum:MGLLineJoinMiter type:@encode(MGLLineJoin)];
layer.lineMiterLimit = [MGLRuntimeStylingHelper testNumber];
layer.lineRoundLimit = [MGLRuntimeStylingHelper testNumber];
- layer.lineOpacity = [MGLRuntimeStylingHelper testNumber];
+ layer.lineBlur = [MGLRuntimeStylingHelper testNumber];
layer.lineColor = [MGLRuntimeStylingHelper testColor];
- layer.lineTranslate = [MGLRuntimeStylingHelper testOffset];
- layer.lineTranslateAnchor = [MGLRuntimeStylingHelper testEnum:MGLLineTranslateAnchorViewport type:@encode(MGLLineTranslateAnchor)];
- layer.lineWidth = [MGLRuntimeStylingHelper testNumber];
+ layer.lineDasharray = [MGLRuntimeStylingHelper testDashArray];
layer.lineGapWidth = [MGLRuntimeStylingHelper testNumber];
layer.lineOffset = [MGLRuntimeStylingHelper testNumber];
- layer.lineBlur = [MGLRuntimeStylingHelper testNumber];
- layer.lineDasharray = [MGLRuntimeStylingHelper testDashArray];
+ layer.lineOpacity = [MGLRuntimeStylingHelper testNumber];
layer.linePattern = [MGLRuntimeStylingHelper testString];
+ layer.lineTranslate = [MGLRuntimeStylingHelper testOffset];
+ layer.lineTranslateAnchor = [MGLRuntimeStylingHelper testEnum:MGLLineTranslateAnchorViewport type:@encode(MGLLineTranslateAnchor)];
+ layer.lineWidth = [MGLRuntimeStylingHelper testNumber];
MGLLineStyleLayer *gLayer = (MGLLineStyleLayer *)[self.mapView.style layerWithIdentifier:@"layerID"];
XCTAssertTrue([gLayer isKindOfClass:[MGLLineStyleLayer class]]);
@@ -39,47 +39,47 @@
XCTAssertEqualObjects(gLayer.lineJoin, [MGLRuntimeStylingHelper testEnum:MGLLineJoinMiter type:@encode(MGLLineJoin)]);
XCTAssertEqualObjects(gLayer.lineMiterLimit, [MGLRuntimeStylingHelper testNumber]);
XCTAssertEqualObjects(gLayer.lineRoundLimit, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.lineOpacity, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.lineBlur, [MGLRuntimeStylingHelper testNumber]);
XCTAssertEqualObjects(gLayer.lineColor, [MGLRuntimeStylingHelper testColor]);
+ XCTAssertEqualObjects(gLayer.lineDasharray, [MGLRuntimeStylingHelper testDashArray]);
+ XCTAssertEqualObjects(gLayer.lineGapWidth, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.lineOffset, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.lineOpacity, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.linePattern, [MGLRuntimeStylingHelper testString]);
XCTAssertEqualObjects(gLayer.lineTranslate, [MGLRuntimeStylingHelper testOffset]);
XCTAssert([gLayer.lineTranslateAnchor isKindOfClass:[MGLStyleConstantValue class]]);
XCTAssertEqualObjects(gLayer.lineTranslateAnchor, [MGLRuntimeStylingHelper testEnum:MGLLineTranslateAnchorViewport type:@encode(MGLLineTranslateAnchor)]);
XCTAssertEqualObjects(gLayer.lineWidth, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.lineGapWidth, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.lineOffset, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.lineBlur, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.lineDasharray, [MGLRuntimeStylingHelper testDashArray]);
- XCTAssertEqualObjects(gLayer.linePattern, [MGLRuntimeStylingHelper testString]);
layer.lineCap = [MGLRuntimeStylingHelper testEnumFunction:MGLLineCapSquare type:@encode(MGLLineCap)];
layer.lineJoin = [MGLRuntimeStylingHelper testEnumFunction:MGLLineJoinMiter type:@encode(MGLLineJoin)];
layer.lineMiterLimit = [MGLRuntimeStylingHelper testNumberFunction];
layer.lineRoundLimit = [MGLRuntimeStylingHelper testNumberFunction];
- layer.lineOpacity = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.lineBlur = [MGLRuntimeStylingHelper testNumberFunction];
layer.lineColor = [MGLRuntimeStylingHelper testColorFunction];
- layer.lineTranslate = [MGLRuntimeStylingHelper testOffsetFunction];
- layer.lineTranslateAnchor = [MGLRuntimeStylingHelper testEnumFunction:MGLLineTranslateAnchorViewport type:@encode(MGLLineTranslateAnchor)];
- layer.lineWidth = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.lineDasharray = [MGLRuntimeStylingHelper testDashArrayFunction];
layer.lineGapWidth = [MGLRuntimeStylingHelper testNumberFunction];
layer.lineOffset = [MGLRuntimeStylingHelper testNumberFunction];
- layer.lineBlur = [MGLRuntimeStylingHelper testNumberFunction];
- layer.lineDasharray = [MGLRuntimeStylingHelper testDashArrayFunction];
+ layer.lineOpacity = [MGLRuntimeStylingHelper testNumberFunction];
layer.linePattern = [MGLRuntimeStylingHelper testStringFunction];
+ layer.lineTranslate = [MGLRuntimeStylingHelper testOffsetFunction];
+ layer.lineTranslateAnchor = [MGLRuntimeStylingHelper testEnumFunction:MGLLineTranslateAnchorViewport type:@encode(MGLLineTranslateAnchor)];
+ layer.lineWidth = [MGLRuntimeStylingHelper testNumberFunction];
XCTAssertEqualObjects(gLayer.lineCap, [MGLRuntimeStylingHelper testEnumFunction:MGLLineCapSquare type:@encode(MGLLineCap)]);
XCTAssertEqualObjects(gLayer.lineJoin, [MGLRuntimeStylingHelper testEnumFunction:MGLLineJoinMiter type:@encode(MGLLineJoin)]);
XCTAssertEqualObjects(gLayer.lineMiterLimit, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.lineRoundLimit, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.lineOpacity, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.lineBlur, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.lineColor, [MGLRuntimeStylingHelper testColorFunction]);
- XCTAssertEqualObjects(gLayer.lineTranslate, [MGLRuntimeStylingHelper testOffsetFunction]);
- XCTAssertEqualObjects(gLayer.lineTranslateAnchor, [MGLRuntimeStylingHelper testEnumFunction:MGLLineTranslateAnchorViewport type:@encode(MGLLineTranslateAnchor)]);
- XCTAssertEqualObjects(gLayer.lineWidth, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.lineDasharray, [MGLRuntimeStylingHelper testDashArrayFunction]);
XCTAssertEqualObjects(gLayer.lineGapWidth, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.lineOffset, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.lineBlur, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.lineDasharray, [MGLRuntimeStylingHelper testDashArrayFunction]);
+ XCTAssertEqualObjects(gLayer.lineOpacity, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.linePattern, [MGLRuntimeStylingHelper testStringFunction]);
+ XCTAssertEqualObjects(gLayer.lineTranslate, [MGLRuntimeStylingHelper testOffsetFunction]);
+ XCTAssertEqualObjects(gLayer.lineTranslateAnchor, [MGLRuntimeStylingHelper testEnumFunction:MGLLineTranslateAnchorViewport type:@encode(MGLLineTranslateAnchor)]);
+ XCTAssertEqualObjects(gLayer.lineWidth, [MGLRuntimeStylingHelper testNumberFunction]);
}
@end
diff --git a/platform/darwin/test/MGLOfflineStorageTests.m b/platform/darwin/test/MGLOfflineStorageTests.m
index cd13a9262e..07540b5645 100644
--- a/platform/darwin/test/MGLOfflineStorageTests.m
+++ b/platform/darwin/test/MGLOfflineStorageTests.m
@@ -19,6 +19,7 @@
}];
if ([MGLOfflineStorage sharedOfflineStorage].packs) {
[expectation fulfill];
+ [self waitForExpectationsWithTimeout:0 handler:nil];
} else {
[self waitForExpectationsWithTimeout:2 handler:nil];
}
diff --git a/platform/darwin/test/MGLRasterStyleLayerTests.m b/platform/darwin/test/MGLRasterStyleLayerTests.m
index ef7ab0263f..84fd0fe3e5 100644
--- a/platform/darwin/test/MGLRasterStyleLayerTests.m
+++ b/platform/darwin/test/MGLRasterStyleLayerTests.m
@@ -1,9 +1,9 @@
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
-#import "MGLMapViewTests.h"
+#import "MGLStyleLayerTests.h"
-@interface MGLRasterLayerTests : MGLMapViewTests
+@interface MGLRasterLayerTests : MGLStyleLayerTests
@end
@implementation MGLRasterLayerTests
@@ -16,39 +16,39 @@
MGLRasterStyleLayer *layer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
[self.mapView.style addLayer:layer];
- layer.rasterOpacity = [MGLRuntimeStylingHelper testNumber];
- layer.rasterHueRotate = [MGLRuntimeStylingHelper testNumber];
- layer.rasterBrightnessMin = [MGLRuntimeStylingHelper testNumber];
- layer.rasterBrightnessMax = [MGLRuntimeStylingHelper testNumber];
- layer.rasterSaturation = [MGLRuntimeStylingHelper testNumber];
+ layer.maximumRasterBrightness = [MGLRuntimeStylingHelper testNumber];
+ layer.minimumRasterBrightness = [MGLRuntimeStylingHelper testNumber];
layer.rasterContrast = [MGLRuntimeStylingHelper testNumber];
layer.rasterFadeDuration = [MGLRuntimeStylingHelper testNumber];
+ layer.rasterHueRotate = [MGLRuntimeStylingHelper testNumber];
+ layer.rasterOpacity = [MGLRuntimeStylingHelper testNumber];
+ layer.rasterSaturation = [MGLRuntimeStylingHelper testNumber];
MGLRasterStyleLayer *gLayer = (MGLRasterStyleLayer *)[self.mapView.style layerWithIdentifier:@"layerID"];
XCTAssertTrue([gLayer isKindOfClass:[MGLRasterStyleLayer class]]);
- XCTAssertEqualObjects(gLayer.rasterOpacity, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.rasterHueRotate, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.rasterBrightnessMin, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.rasterBrightnessMax, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.rasterSaturation, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.maximumRasterBrightness, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.minimumRasterBrightness, [MGLRuntimeStylingHelper testNumber]);
XCTAssertEqualObjects(gLayer.rasterContrast, [MGLRuntimeStylingHelper testNumber]);
XCTAssertEqualObjects(gLayer.rasterFadeDuration, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.rasterHueRotate, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.rasterOpacity, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.rasterSaturation, [MGLRuntimeStylingHelper testNumber]);
- layer.rasterOpacity = [MGLRuntimeStylingHelper testNumberFunction];
- layer.rasterHueRotate = [MGLRuntimeStylingHelper testNumberFunction];
- layer.rasterBrightnessMin = [MGLRuntimeStylingHelper testNumberFunction];
- layer.rasterBrightnessMax = [MGLRuntimeStylingHelper testNumberFunction];
- layer.rasterSaturation = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.maximumRasterBrightness = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.minimumRasterBrightness = [MGLRuntimeStylingHelper testNumberFunction];
layer.rasterContrast = [MGLRuntimeStylingHelper testNumberFunction];
layer.rasterFadeDuration = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.rasterHueRotate = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.rasterOpacity = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.rasterSaturation = [MGLRuntimeStylingHelper testNumberFunction];
- XCTAssertEqualObjects(gLayer.rasterOpacity, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.rasterHueRotate, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.rasterBrightnessMin, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.rasterBrightnessMax, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.rasterSaturation, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.maximumRasterBrightness, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.minimumRasterBrightness, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.rasterContrast, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.rasterFadeDuration, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.rasterHueRotate, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.rasterOpacity, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.rasterSaturation, [MGLRuntimeStylingHelper testNumberFunction]);
}
@end
diff --git a/platform/darwin/test/MGLMapViewTests.h b/platform/darwin/test/MGLStyleLayerTests.h
index da94281165..f81e075e03 100644
--- a/platform/darwin/test/MGLMapViewTests.h
+++ b/platform/darwin/test/MGLStyleLayerTests.h
@@ -2,7 +2,7 @@
#import "MGLRuntimeStylingHelper.h"
#import <XCTest/XCTest.h>
-@interface MGLMapViewTests : XCTestCase <MGLMapViewDelegate>
+@interface MGLStyleLayerTests : XCTestCase <MGLMapViewDelegate>
@property (nonatomic) IBOutlet MGLMapView *mapView;
@property (nonatomic) XCTestExpectation *expectation;
diff --git a/platform/darwin/test/MGLMapViewTests.m b/platform/darwin/test/MGLStyleLayerTests.m
index 63ff3501ca..74c6b2f906 100644
--- a/platform/darwin/test/MGLMapViewTests.m
+++ b/platform/darwin/test/MGLStyleLayerTests.m
@@ -1,6 +1,6 @@
-#import "MGLMapViewTests.h"
+#import "MGLStyleLayerTests.h"
-@implementation MGLMapViewTests
+@implementation MGLStyleLayerTests
- (void)setUp {
[super setUp];
@@ -14,7 +14,7 @@
_mapView.delegate = self;
#else
[MGLAccountManager setAccessToken:@"pk.feedcafedeadbeefbadebede"];
- NSWindowController *windowController = [[NSWindowController alloc] initWithWindowNibName:@"MGLMapViewTests" owner:self];
+ NSWindowController *windowController = [[NSWindowController alloc] initWithWindowNibName:@"MGLStyleLayerTests" owner:self];
[windowController showWindow:nil];
#endif
}
diff --git a/platform/darwin/test/MGLMapViewTests.xib b/platform/darwin/test/MGLStyleLayerTests.xib
index cc336191ef..23ad22e7e3 100644
--- a/platform/darwin/test/MGLMapViewTests.xib
+++ b/platform/darwin/test/MGLStyleLayerTests.xib
@@ -4,14 +4,14 @@
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="10117"/>
</dependencies>
<objects>
- <customObject id="-2" userLabel="File's Owner" customClass="MGLMapViewTests">
+ <customObject id="-2" userLabel="File's Owner" customClass="MGLStyleLayerTests">
<connections>
<outlet property="mapView" destination="6RL-d9-juy" id="0ch-aR-Um6"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
- <window title="MGLMapViewTests" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
+ <window title="MGLStyleLayerTests" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="256" height="256"/>
diff --git a/platform/darwin/test/MGLStyleTests.mm b/platform/darwin/test/MGLStyleTests.mm
index 07e012edc6..4c0c163b38 100644
--- a/platform/darwin/test/MGLStyleTests.mm
+++ b/platform/darwin/test/MGLStyleTests.mm
@@ -1,4 +1,16 @@
-#import "MGLStyle.h"
+#import "MGLMapView.h"
+#import "MGLStyle_Private.h"
+
+#import "MGLGeoJSONSource.h"
+#import "MGLRasterSource.h"
+#import "MGLVectorSource.h"
+
+#import "MGLBackgroundStyleLayer.h"
+#import "MGLCircleStyleLayer.h"
+#import "MGLFillStyleLayer.h"
+#import "MGLLineStyleLayer.h"
+#import "MGLRasterStyleLayer.h"
+#import "MGLSymbolStyleLayer.h"
#import "NSBundle+MGLAdditions.h"
@@ -8,10 +20,21 @@
#import <objc/runtime.h>
@interface MGLStyleTests : XCTestCase
+
+@property (nonatomic) MGLMapView *mapView;
+@property (nonatomic) MGLStyle *style;
+
@end
@implementation MGLStyleTests
+- (void)setUp {
+ [super setUp];
+
+ self.mapView = [[MGLMapView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
+ self.style = [[MGLStyle alloc] initWithMapView:self.mapView];
+}
+
- (void)testUnversionedStyleURLs {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
@@ -92,6 +115,56 @@
}];
}
+- (void)testAddingSourcesTwice {
+ MGLGeoJSONSource *geoJSONSource = [[MGLGeoJSONSource alloc] initWithIdentifier:@"geoJSONSource" features:@[] options:nil];
+ [self.style addSource:geoJSONSource];
+ XCTAssertThrowsSpecificNamed([self.style addSource:geoJSONSource], NSException, @"MGLRedundantSourceException");
+
+ MGLRasterSource *rasterSource = [[MGLRasterSource alloc] initWithIdentifier:@"rasterSource" URL:[NSURL new] tileSize:42];
+ [self.style addSource:rasterSource];
+ XCTAssertThrowsSpecificNamed([self.style addSource:rasterSource], NSException, @"MGLRedundantSourceException");
+
+ MGLVectorSource *vectorSource = [[MGLVectorSource alloc] initWithIdentifier:@"vectorSource" URL:[NSURL new]];
+ [self.style addSource:vectorSource];
+ XCTAssertThrowsSpecificNamed([self.style addSource:vectorSource], NSException, @"MGLRedundantSourceException");
+}
+
+- (void)testAddingSourcesWithDuplicateIdentifiers {
+ MGLVectorSource *source1 = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" URL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
+ MGLVectorSource *source2 = [[MGLVectorSource alloc] initWithIdentifier:@"my-source" URL:[NSURL URLWithString:@"mapbox://mapbox.mapbox-terrain-v2"]];
+
+ [self.style addSource: source1];
+ XCTAssertThrowsSpecificNamed([self.style addSource: source2], NSException, @"MGLRedundantSourceIdentiferException");
+}
+
+- (void)testAddingLayersTwice {
+ MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithIdentifier:@"geoJSONSource" features:@[] options:nil];
+
+ MGLBackgroundStyleLayer *backgroundLayer = [[MGLBackgroundStyleLayer alloc] initWithIdentifier:@"backgroundLayer"];
+ [self.style addLayer:backgroundLayer];
+ XCTAssertThrowsSpecificNamed([self.style addLayer:backgroundLayer], NSException, @"MGLRedundantLayerException");
+
+ MGLCircleStyleLayer *circleLayer = [[MGLCircleStyleLayer alloc] initWithIdentifier:@"circleLayer" source:source];
+ [self.style addLayer:circleLayer];
+ XCTAssertThrowsSpecificNamed([self.style addLayer:circleLayer], NSException, @"MGLRedundantLayerException");
+
+ MGLFillStyleLayer *fillLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"fillLayer" source:source];
+ [self.style addLayer:fillLayer];
+ XCTAssertThrowsSpecificNamed([self.style addLayer:fillLayer], NSException, @"MGLRedundantLayerException");
+
+ MGLLineStyleLayer *lineLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"lineLayer" source:source];
+ [self.style addLayer:lineLayer];
+ XCTAssertThrowsSpecificNamed([self.style addLayer:lineLayer], NSException, @"MGLRedundantLayerException");
+
+ MGLRasterStyleLayer *rasterLayer = [[MGLRasterStyleLayer alloc] initWithIdentifier:@"rasterLayer" source:source];
+ [self.style addLayer:rasterLayer];
+ XCTAssertThrowsSpecificNamed([self.style addLayer:rasterLayer], NSException, @"MGLRedundantLayerException");
+
+ MGLSymbolStyleLayer *symbolLayer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"symbolLayer" source:source];
+ [self.style addLayer:symbolLayer];
+ XCTAssertThrowsSpecificNamed([self.style addLayer:symbolLayer], NSException, @"MGLRedundantLayerException");
+}
+
- (NSString *)stringWithContentsOfStyleHeader {
NSURL *styleHeaderURL = [[[NSBundle mgl_frameworkBundle].bundleURL
URLByAppendingPathComponent:@"Headers" isDirectory:YES]
diff --git a/platform/darwin/test/MGLSymbolStyleLayerTests.m b/platform/darwin/test/MGLSymbolStyleLayerTests.m
index 1761a71e0c..e77c4f6f39 100644
--- a/platform/darwin/test/MGLSymbolStyleLayerTests.m
+++ b/platform/darwin/test/MGLSymbolStyleLayerTests.m
@@ -1,9 +1,9 @@
// This file is generated.
// Edit platform/darwin/scripts/generate-style-code.js, then run `make style-code-darwin`.
-#import "MGLMapViewTests.h"
+#import "MGLStyleLayerTests.h"
-@interface MGLSymbolLayerTests : MGLMapViewTests
+@interface MGLSymbolLayerTests : MGLStyleLayerTests
@end
@implementation MGLSymbolLayerTests
@@ -16,211 +16,211 @@
MGLSymbolStyleLayer *layer = [[MGLSymbolStyleLayer alloc] initWithIdentifier:@"layerID" source:source];
[self.mapView.style addLayer:layer];
- layer.symbolPlacement = [MGLRuntimeStylingHelper testEnum:MGLSymbolPlacementLine type:@encode(MGLSymbolPlacement)];
- layer.symbolSpacing = [MGLRuntimeStylingHelper testNumber];
- layer.symbolAvoidEdges = [MGLRuntimeStylingHelper testBool];
layer.iconAllowOverlap = [MGLRuntimeStylingHelper testBool];
layer.iconIgnorePlacement = [MGLRuntimeStylingHelper testBool];
+ layer.iconImageName = [MGLRuntimeStylingHelper testString];
+ layer.iconKeepUpright = [MGLRuntimeStylingHelper testBool];
+ layer.iconOffset = [MGLRuntimeStylingHelper testOffset];
layer.iconOptional = [MGLRuntimeStylingHelper testBool];
+ layer.iconPadding = [MGLRuntimeStylingHelper testNumber];
+ layer.iconRotate = [MGLRuntimeStylingHelper testNumber];
layer.iconRotationAlignment = [MGLRuntimeStylingHelper testEnum:MGLIconRotationAlignmentAuto type:@encode(MGLIconRotationAlignment)];
layer.iconSize = [MGLRuntimeStylingHelper testNumber];
layer.iconTextFit = [MGLRuntimeStylingHelper testEnum:MGLIconTextFitBoth type:@encode(MGLIconTextFit)];
layer.iconTextFitPadding = [MGLRuntimeStylingHelper testPadding];
- layer.iconImage = [MGLRuntimeStylingHelper testString];
- layer.iconRotate = [MGLRuntimeStylingHelper testNumber];
- layer.iconPadding = [MGLRuntimeStylingHelper testNumber];
- layer.iconKeepUpright = [MGLRuntimeStylingHelper testBool];
- layer.iconOffset = [MGLRuntimeStylingHelper testOffset];
- layer.textPitchAlignment = [MGLRuntimeStylingHelper testEnum:MGLTextPitchAlignmentAuto type:@encode(MGLTextPitchAlignment)];
- layer.textRotationAlignment = [MGLRuntimeStylingHelper testEnum:MGLTextRotationAlignmentAuto type:@encode(MGLTextRotationAlignment)];
+ layer.symbolAvoidEdges = [MGLRuntimeStylingHelper testBool];
+ layer.symbolPlacement = [MGLRuntimeStylingHelper testEnum:MGLSymbolPlacementLine type:@encode(MGLSymbolPlacement)];
+ layer.symbolSpacing = [MGLRuntimeStylingHelper testNumber];
+ layer.textAllowOverlap = [MGLRuntimeStylingHelper testBool];
+ layer.textAnchor = [MGLRuntimeStylingHelper testEnum:MGLTextAnchorBottomRight type:@encode(MGLTextAnchor)];
layer.textField = [MGLRuntimeStylingHelper testString];
layer.textFont = [MGLRuntimeStylingHelper testFont];
- layer.textSize = [MGLRuntimeStylingHelper testNumber];
- layer.textMaxWidth = [MGLRuntimeStylingHelper testNumber];
- layer.textLineHeight = [MGLRuntimeStylingHelper testNumber];
- layer.textLetterSpacing = [MGLRuntimeStylingHelper testNumber];
+ layer.textIgnorePlacement = [MGLRuntimeStylingHelper testBool];
layer.textJustify = [MGLRuntimeStylingHelper testEnum:MGLTextJustifyRight type:@encode(MGLTextJustify)];
- layer.textAnchor = [MGLRuntimeStylingHelper testEnum:MGLTextAnchorBottomRight type:@encode(MGLTextAnchor)];
- layer.textMaxAngle = [MGLRuntimeStylingHelper testNumber];
- layer.textRotate = [MGLRuntimeStylingHelper testNumber];
- layer.textPadding = [MGLRuntimeStylingHelper testNumber];
layer.textKeepUpright = [MGLRuntimeStylingHelper testBool];
- layer.textTransform = [MGLRuntimeStylingHelper testEnum:MGLTextTransformLowercase type:@encode(MGLTextTransform)];
+ layer.textLetterSpacing = [MGLRuntimeStylingHelper testNumber];
+ layer.textLineHeight = [MGLRuntimeStylingHelper testNumber];
+ layer.textMaxAngle = [MGLRuntimeStylingHelper testNumber];
+ layer.textMaxWidth = [MGLRuntimeStylingHelper testNumber];
layer.textOffset = [MGLRuntimeStylingHelper testOffset];
- layer.textAllowOverlap = [MGLRuntimeStylingHelper testBool];
- layer.textIgnorePlacement = [MGLRuntimeStylingHelper testBool];
layer.textOptional = [MGLRuntimeStylingHelper testBool];
- layer.iconOpacity = [MGLRuntimeStylingHelper testNumber];
+ layer.textPadding = [MGLRuntimeStylingHelper testNumber];
+ layer.textPitchAlignment = [MGLRuntimeStylingHelper testEnum:MGLTextPitchAlignmentAuto type:@encode(MGLTextPitchAlignment)];
+ layer.textRotate = [MGLRuntimeStylingHelper testNumber];
+ layer.textRotationAlignment = [MGLRuntimeStylingHelper testEnum:MGLTextRotationAlignmentAuto type:@encode(MGLTextRotationAlignment)];
+ layer.textSize = [MGLRuntimeStylingHelper testNumber];
+ layer.textTransform = [MGLRuntimeStylingHelper testEnum:MGLTextTransformLowercase type:@encode(MGLTextTransform)];
layer.iconColor = [MGLRuntimeStylingHelper testColor];
+ layer.iconHaloBlur = [MGLRuntimeStylingHelper testNumber];
layer.iconHaloColor = [MGLRuntimeStylingHelper testColor];
layer.iconHaloWidth = [MGLRuntimeStylingHelper testNumber];
- layer.iconHaloBlur = [MGLRuntimeStylingHelper testNumber];
+ layer.iconOpacity = [MGLRuntimeStylingHelper testNumber];
layer.iconTranslate = [MGLRuntimeStylingHelper testOffset];
layer.iconTranslateAnchor = [MGLRuntimeStylingHelper testEnum:MGLIconTranslateAnchorViewport type:@encode(MGLIconTranslateAnchor)];
- layer.textOpacity = [MGLRuntimeStylingHelper testNumber];
layer.textColor = [MGLRuntimeStylingHelper testColor];
+ layer.textHaloBlur = [MGLRuntimeStylingHelper testNumber];
layer.textHaloColor = [MGLRuntimeStylingHelper testColor];
layer.textHaloWidth = [MGLRuntimeStylingHelper testNumber];
- layer.textHaloBlur = [MGLRuntimeStylingHelper testNumber];
+ layer.textOpacity = [MGLRuntimeStylingHelper testNumber];
layer.textTranslate = [MGLRuntimeStylingHelper testOffset];
layer.textTranslateAnchor = [MGLRuntimeStylingHelper testEnum:MGLTextTranslateAnchorViewport type:@encode(MGLTextTranslateAnchor)];
MGLSymbolStyleLayer *gLayer = (MGLSymbolStyleLayer *)[self.mapView.style layerWithIdentifier:@"layerID"];
XCTAssertTrue([gLayer isKindOfClass:[MGLSymbolStyleLayer class]]);
- XCTAssert([gLayer.symbolPlacement isKindOfClass:[MGLStyleConstantValue class]]);
- XCTAssertEqualObjects(gLayer.symbolPlacement, [MGLRuntimeStylingHelper testEnum:MGLSymbolPlacementLine type:@encode(MGLSymbolPlacement)]);
- XCTAssertEqualObjects(gLayer.symbolSpacing, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.symbolAvoidEdges, [MGLRuntimeStylingHelper testBool]);
XCTAssertEqualObjects(gLayer.iconAllowOverlap, [MGLRuntimeStylingHelper testBool]);
XCTAssertEqualObjects(gLayer.iconIgnorePlacement, [MGLRuntimeStylingHelper testBool]);
+ XCTAssertEqualObjects(gLayer.iconImageName, [MGLRuntimeStylingHelper testString]);
+ XCTAssertEqualObjects(gLayer.iconKeepUpright, [MGLRuntimeStylingHelper testBool]);
+ XCTAssertEqualObjects(gLayer.iconOffset, [MGLRuntimeStylingHelper testOffset]);
XCTAssertEqualObjects(gLayer.iconOptional, [MGLRuntimeStylingHelper testBool]);
+ XCTAssertEqualObjects(gLayer.iconPadding, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.iconRotate, [MGLRuntimeStylingHelper testNumber]);
XCTAssert([gLayer.iconRotationAlignment isKindOfClass:[MGLStyleConstantValue class]]);
XCTAssertEqualObjects(gLayer.iconRotationAlignment, [MGLRuntimeStylingHelper testEnum:MGLIconRotationAlignmentAuto type:@encode(MGLIconRotationAlignment)]);
XCTAssertEqualObjects(gLayer.iconSize, [MGLRuntimeStylingHelper testNumber]);
XCTAssert([gLayer.iconTextFit isKindOfClass:[MGLStyleConstantValue class]]);
XCTAssertEqualObjects(gLayer.iconTextFit, [MGLRuntimeStylingHelper testEnum:MGLIconTextFitBoth type:@encode(MGLIconTextFit)]);
XCTAssertEqualObjects(gLayer.iconTextFitPadding, [MGLRuntimeStylingHelper testPadding]);
- XCTAssertEqualObjects(gLayer.iconImage, [MGLRuntimeStylingHelper testString]);
- XCTAssertEqualObjects(gLayer.iconRotate, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.iconPadding, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.iconKeepUpright, [MGLRuntimeStylingHelper testBool]);
- XCTAssertEqualObjects(gLayer.iconOffset, [MGLRuntimeStylingHelper testOffset]);
- XCTAssert([gLayer.textPitchAlignment isKindOfClass:[MGLStyleConstantValue class]]);
- XCTAssertEqualObjects(gLayer.textPitchAlignment, [MGLRuntimeStylingHelper testEnum:MGLTextPitchAlignmentAuto type:@encode(MGLTextPitchAlignment)]);
- XCTAssert([gLayer.textRotationAlignment isKindOfClass:[MGLStyleConstantValue class]]);
- XCTAssertEqualObjects(gLayer.textRotationAlignment, [MGLRuntimeStylingHelper testEnum:MGLTextRotationAlignmentAuto type:@encode(MGLTextRotationAlignment)]);
+ XCTAssertEqualObjects(gLayer.symbolAvoidEdges, [MGLRuntimeStylingHelper testBool]);
+ XCTAssert([gLayer.symbolPlacement isKindOfClass:[MGLStyleConstantValue class]]);
+ XCTAssertEqualObjects(gLayer.symbolPlacement, [MGLRuntimeStylingHelper testEnum:MGLSymbolPlacementLine type:@encode(MGLSymbolPlacement)]);
+ XCTAssertEqualObjects(gLayer.symbolSpacing, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.textAllowOverlap, [MGLRuntimeStylingHelper testBool]);
+ XCTAssert([gLayer.textAnchor isKindOfClass:[MGLStyleConstantValue class]]);
+ XCTAssertEqualObjects(gLayer.textAnchor, [MGLRuntimeStylingHelper testEnum:MGLTextAnchorBottomRight type:@encode(MGLTextAnchor)]);
XCTAssertEqualObjects(gLayer.textField, [MGLRuntimeStylingHelper testString]);
XCTAssertEqualObjects(gLayer.textFont, [MGLRuntimeStylingHelper testFont]);
- XCTAssertEqualObjects(gLayer.textSize, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.textMaxWidth, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.textLineHeight, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.textLetterSpacing, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.textIgnorePlacement, [MGLRuntimeStylingHelper testBool]);
XCTAssert([gLayer.textJustify isKindOfClass:[MGLStyleConstantValue class]]);
XCTAssertEqualObjects(gLayer.textJustify, [MGLRuntimeStylingHelper testEnum:MGLTextJustifyRight type:@encode(MGLTextJustify)]);
- XCTAssert([gLayer.textAnchor isKindOfClass:[MGLStyleConstantValue class]]);
- XCTAssertEqualObjects(gLayer.textAnchor, [MGLRuntimeStylingHelper testEnum:MGLTextAnchorBottomRight type:@encode(MGLTextAnchor)]);
+ XCTAssertEqualObjects(gLayer.textKeepUpright, [MGLRuntimeStylingHelper testBool]);
+ XCTAssertEqualObjects(gLayer.textLetterSpacing, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.textLineHeight, [MGLRuntimeStylingHelper testNumber]);
XCTAssertEqualObjects(gLayer.textMaxAngle, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.textRotate, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.textMaxWidth, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.textOffset, [MGLRuntimeStylingHelper testOffset]);
+ XCTAssertEqualObjects(gLayer.textOptional, [MGLRuntimeStylingHelper testBool]);
XCTAssertEqualObjects(gLayer.textPadding, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.textKeepUpright, [MGLRuntimeStylingHelper testBool]);
+ XCTAssert([gLayer.textPitchAlignment isKindOfClass:[MGLStyleConstantValue class]]);
+ XCTAssertEqualObjects(gLayer.textPitchAlignment, [MGLRuntimeStylingHelper testEnum:MGLTextPitchAlignmentAuto type:@encode(MGLTextPitchAlignment)]);
+ XCTAssertEqualObjects(gLayer.textRotate, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssert([gLayer.textRotationAlignment isKindOfClass:[MGLStyleConstantValue class]]);
+ XCTAssertEqualObjects(gLayer.textRotationAlignment, [MGLRuntimeStylingHelper testEnum:MGLTextRotationAlignmentAuto type:@encode(MGLTextRotationAlignment)]);
+ XCTAssertEqualObjects(gLayer.textSize, [MGLRuntimeStylingHelper testNumber]);
XCTAssert([gLayer.textTransform isKindOfClass:[MGLStyleConstantValue class]]);
XCTAssertEqualObjects(gLayer.textTransform, [MGLRuntimeStylingHelper testEnum:MGLTextTransformLowercase type:@encode(MGLTextTransform)]);
- XCTAssertEqualObjects(gLayer.textOffset, [MGLRuntimeStylingHelper testOffset]);
- XCTAssertEqualObjects(gLayer.textAllowOverlap, [MGLRuntimeStylingHelper testBool]);
- XCTAssertEqualObjects(gLayer.textIgnorePlacement, [MGLRuntimeStylingHelper testBool]);
- XCTAssertEqualObjects(gLayer.textOptional, [MGLRuntimeStylingHelper testBool]);
- XCTAssertEqualObjects(gLayer.iconOpacity, [MGLRuntimeStylingHelper testNumber]);
XCTAssertEqualObjects(gLayer.iconColor, [MGLRuntimeStylingHelper testColor]);
+ XCTAssertEqualObjects(gLayer.iconHaloBlur, [MGLRuntimeStylingHelper testNumber]);
XCTAssertEqualObjects(gLayer.iconHaloColor, [MGLRuntimeStylingHelper testColor]);
XCTAssertEqualObjects(gLayer.iconHaloWidth, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.iconHaloBlur, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.iconOpacity, [MGLRuntimeStylingHelper testNumber]);
XCTAssertEqualObjects(gLayer.iconTranslate, [MGLRuntimeStylingHelper testOffset]);
XCTAssert([gLayer.iconTranslateAnchor isKindOfClass:[MGLStyleConstantValue class]]);
XCTAssertEqualObjects(gLayer.iconTranslateAnchor, [MGLRuntimeStylingHelper testEnum:MGLIconTranslateAnchorViewport type:@encode(MGLIconTranslateAnchor)]);
- XCTAssertEqualObjects(gLayer.textOpacity, [MGLRuntimeStylingHelper testNumber]);
XCTAssertEqualObjects(gLayer.textColor, [MGLRuntimeStylingHelper testColor]);
+ XCTAssertEqualObjects(gLayer.textHaloBlur, [MGLRuntimeStylingHelper testNumber]);
XCTAssertEqualObjects(gLayer.textHaloColor, [MGLRuntimeStylingHelper testColor]);
XCTAssertEqualObjects(gLayer.textHaloWidth, [MGLRuntimeStylingHelper testNumber]);
- XCTAssertEqualObjects(gLayer.textHaloBlur, [MGLRuntimeStylingHelper testNumber]);
+ XCTAssertEqualObjects(gLayer.textOpacity, [MGLRuntimeStylingHelper testNumber]);
XCTAssertEqualObjects(gLayer.textTranslate, [MGLRuntimeStylingHelper testOffset]);
XCTAssert([gLayer.textTranslateAnchor isKindOfClass:[MGLStyleConstantValue class]]);
XCTAssertEqualObjects(gLayer.textTranslateAnchor, [MGLRuntimeStylingHelper testEnum:MGLTextTranslateAnchorViewport type:@encode(MGLTextTranslateAnchor)]);
- layer.symbolPlacement = [MGLRuntimeStylingHelper testEnumFunction:MGLSymbolPlacementLine type:@encode(MGLSymbolPlacement)];
- layer.symbolSpacing = [MGLRuntimeStylingHelper testNumberFunction];
- layer.symbolAvoidEdges = [MGLRuntimeStylingHelper testBoolFunction];
layer.iconAllowOverlap = [MGLRuntimeStylingHelper testBoolFunction];
layer.iconIgnorePlacement = [MGLRuntimeStylingHelper testBoolFunction];
+ layer.iconImageName = [MGLRuntimeStylingHelper testStringFunction];
+ layer.iconKeepUpright = [MGLRuntimeStylingHelper testBoolFunction];
+ layer.iconOffset = [MGLRuntimeStylingHelper testOffsetFunction];
layer.iconOptional = [MGLRuntimeStylingHelper testBoolFunction];
+ layer.iconPadding = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.iconRotate = [MGLRuntimeStylingHelper testNumberFunction];
layer.iconRotationAlignment = [MGLRuntimeStylingHelper testEnumFunction:MGLIconRotationAlignmentAuto type:@encode(MGLIconRotationAlignment)];
layer.iconSize = [MGLRuntimeStylingHelper testNumberFunction];
layer.iconTextFit = [MGLRuntimeStylingHelper testEnumFunction:MGLIconTextFitBoth type:@encode(MGLIconTextFit)];
layer.iconTextFitPadding = [MGLRuntimeStylingHelper testPaddingFunction];
- layer.iconImage = [MGLRuntimeStylingHelper testStringFunction];
- layer.iconRotate = [MGLRuntimeStylingHelper testNumberFunction];
- layer.iconPadding = [MGLRuntimeStylingHelper testNumberFunction];
- layer.iconKeepUpright = [MGLRuntimeStylingHelper testBoolFunction];
- layer.iconOffset = [MGLRuntimeStylingHelper testOffsetFunction];
- layer.textPitchAlignment = [MGLRuntimeStylingHelper testEnumFunction:MGLTextPitchAlignmentAuto type:@encode(MGLTextPitchAlignment)];
- layer.textRotationAlignment = [MGLRuntimeStylingHelper testEnumFunction:MGLTextRotationAlignmentAuto type:@encode(MGLTextRotationAlignment)];
+ layer.symbolAvoidEdges = [MGLRuntimeStylingHelper testBoolFunction];
+ layer.symbolPlacement = [MGLRuntimeStylingHelper testEnumFunction:MGLSymbolPlacementLine type:@encode(MGLSymbolPlacement)];
+ layer.symbolSpacing = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.textAllowOverlap = [MGLRuntimeStylingHelper testBoolFunction];
+ layer.textAnchor = [MGLRuntimeStylingHelper testEnumFunction:MGLTextAnchorBottomRight type:@encode(MGLTextAnchor)];
layer.textField = [MGLRuntimeStylingHelper testStringFunction];
layer.textFont = [MGLRuntimeStylingHelper testFontFunction];
- layer.textSize = [MGLRuntimeStylingHelper testNumberFunction];
- layer.textMaxWidth = [MGLRuntimeStylingHelper testNumberFunction];
- layer.textLineHeight = [MGLRuntimeStylingHelper testNumberFunction];
- layer.textLetterSpacing = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.textIgnorePlacement = [MGLRuntimeStylingHelper testBoolFunction];
layer.textJustify = [MGLRuntimeStylingHelper testEnumFunction:MGLTextJustifyRight type:@encode(MGLTextJustify)];
- layer.textAnchor = [MGLRuntimeStylingHelper testEnumFunction:MGLTextAnchorBottomRight type:@encode(MGLTextAnchor)];
- layer.textMaxAngle = [MGLRuntimeStylingHelper testNumberFunction];
- layer.textRotate = [MGLRuntimeStylingHelper testNumberFunction];
- layer.textPadding = [MGLRuntimeStylingHelper testNumberFunction];
layer.textKeepUpright = [MGLRuntimeStylingHelper testBoolFunction];
- layer.textTransform = [MGLRuntimeStylingHelper testEnumFunction:MGLTextTransformLowercase type:@encode(MGLTextTransform)];
+ layer.textLetterSpacing = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.textLineHeight = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.textMaxAngle = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.textMaxWidth = [MGLRuntimeStylingHelper testNumberFunction];
layer.textOffset = [MGLRuntimeStylingHelper testOffsetFunction];
- layer.textAllowOverlap = [MGLRuntimeStylingHelper testBoolFunction];
- layer.textIgnorePlacement = [MGLRuntimeStylingHelper testBoolFunction];
layer.textOptional = [MGLRuntimeStylingHelper testBoolFunction];
- layer.iconOpacity = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.textPadding = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.textPitchAlignment = [MGLRuntimeStylingHelper testEnumFunction:MGLTextPitchAlignmentAuto type:@encode(MGLTextPitchAlignment)];
+ layer.textRotate = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.textRotationAlignment = [MGLRuntimeStylingHelper testEnumFunction:MGLTextRotationAlignmentAuto type:@encode(MGLTextRotationAlignment)];
+ layer.textSize = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.textTransform = [MGLRuntimeStylingHelper testEnumFunction:MGLTextTransformLowercase type:@encode(MGLTextTransform)];
layer.iconColor = [MGLRuntimeStylingHelper testColorFunction];
+ layer.iconHaloBlur = [MGLRuntimeStylingHelper testNumberFunction];
layer.iconHaloColor = [MGLRuntimeStylingHelper testColorFunction];
layer.iconHaloWidth = [MGLRuntimeStylingHelper testNumberFunction];
- layer.iconHaloBlur = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.iconOpacity = [MGLRuntimeStylingHelper testNumberFunction];
layer.iconTranslate = [MGLRuntimeStylingHelper testOffsetFunction];
layer.iconTranslateAnchor = [MGLRuntimeStylingHelper testEnumFunction:MGLIconTranslateAnchorViewport type:@encode(MGLIconTranslateAnchor)];
- layer.textOpacity = [MGLRuntimeStylingHelper testNumberFunction];
layer.textColor = [MGLRuntimeStylingHelper testColorFunction];
+ layer.textHaloBlur = [MGLRuntimeStylingHelper testNumberFunction];
layer.textHaloColor = [MGLRuntimeStylingHelper testColorFunction];
layer.textHaloWidth = [MGLRuntimeStylingHelper testNumberFunction];
- layer.textHaloBlur = [MGLRuntimeStylingHelper testNumberFunction];
+ layer.textOpacity = [MGLRuntimeStylingHelper testNumberFunction];
layer.textTranslate = [MGLRuntimeStylingHelper testOffsetFunction];
layer.textTranslateAnchor = [MGLRuntimeStylingHelper testEnumFunction:MGLTextTranslateAnchorViewport type:@encode(MGLTextTranslateAnchor)];
- XCTAssertEqualObjects(gLayer.symbolPlacement, [MGLRuntimeStylingHelper testEnumFunction:MGLSymbolPlacementLine type:@encode(MGLSymbolPlacement)]);
- XCTAssertEqualObjects(gLayer.symbolSpacing, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.symbolAvoidEdges, [MGLRuntimeStylingHelper testBoolFunction]);
XCTAssertEqualObjects(gLayer.iconAllowOverlap, [MGLRuntimeStylingHelper testBoolFunction]);
XCTAssertEqualObjects(gLayer.iconIgnorePlacement, [MGLRuntimeStylingHelper testBoolFunction]);
+ XCTAssertEqualObjects(gLayer.iconImageName, [MGLRuntimeStylingHelper testStringFunction]);
+ XCTAssertEqualObjects(gLayer.iconKeepUpright, [MGLRuntimeStylingHelper testBoolFunction]);
+ XCTAssertEqualObjects(gLayer.iconOffset, [MGLRuntimeStylingHelper testOffsetFunction]);
XCTAssertEqualObjects(gLayer.iconOptional, [MGLRuntimeStylingHelper testBoolFunction]);
+ XCTAssertEqualObjects(gLayer.iconPadding, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.iconRotate, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.iconRotationAlignment, [MGLRuntimeStylingHelper testEnumFunction:MGLIconRotationAlignmentAuto type:@encode(MGLIconRotationAlignment)]);
XCTAssertEqualObjects(gLayer.iconSize, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.iconTextFit, [MGLRuntimeStylingHelper testEnumFunction:MGLIconTextFitBoth type:@encode(MGLIconTextFit)]);
XCTAssertEqualObjects(gLayer.iconTextFitPadding, [MGLRuntimeStylingHelper testPaddingFunction]);
- XCTAssertEqualObjects(gLayer.iconImage, [MGLRuntimeStylingHelper testStringFunction]);
- XCTAssertEqualObjects(gLayer.iconRotate, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.iconPadding, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.iconKeepUpright, [MGLRuntimeStylingHelper testBoolFunction]);
- XCTAssertEqualObjects(gLayer.iconOffset, [MGLRuntimeStylingHelper testOffsetFunction]);
- XCTAssertEqualObjects(gLayer.textPitchAlignment, [MGLRuntimeStylingHelper testEnumFunction:MGLTextPitchAlignmentAuto type:@encode(MGLTextPitchAlignment)]);
- XCTAssertEqualObjects(gLayer.textRotationAlignment, [MGLRuntimeStylingHelper testEnumFunction:MGLTextRotationAlignmentAuto type:@encode(MGLTextRotationAlignment)]);
+ XCTAssertEqualObjects(gLayer.symbolAvoidEdges, [MGLRuntimeStylingHelper testBoolFunction]);
+ XCTAssertEqualObjects(gLayer.symbolPlacement, [MGLRuntimeStylingHelper testEnumFunction:MGLSymbolPlacementLine type:@encode(MGLSymbolPlacement)]);
+ XCTAssertEqualObjects(gLayer.symbolSpacing, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.textAllowOverlap, [MGLRuntimeStylingHelper testBoolFunction]);
+ XCTAssertEqualObjects(gLayer.textAnchor, [MGLRuntimeStylingHelper testEnumFunction:MGLTextAnchorBottomRight type:@encode(MGLTextAnchor)]);
XCTAssertEqualObjects(gLayer.textField, [MGLRuntimeStylingHelper testStringFunction]);
XCTAssertEqualObjects(gLayer.textFont, [MGLRuntimeStylingHelper testFontFunction]);
- XCTAssertEqualObjects(gLayer.textSize, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.textMaxWidth, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.textLineHeight, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.textLetterSpacing, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.textIgnorePlacement, [MGLRuntimeStylingHelper testBoolFunction]);
XCTAssertEqualObjects(gLayer.textJustify, [MGLRuntimeStylingHelper testEnumFunction:MGLTextJustifyRight type:@encode(MGLTextJustify)]);
- XCTAssertEqualObjects(gLayer.textAnchor, [MGLRuntimeStylingHelper testEnumFunction:MGLTextAnchorBottomRight type:@encode(MGLTextAnchor)]);
- XCTAssertEqualObjects(gLayer.textMaxAngle, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.textRotate, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.textPadding, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.textKeepUpright, [MGLRuntimeStylingHelper testBoolFunction]);
- XCTAssertEqualObjects(gLayer.textTransform, [MGLRuntimeStylingHelper testEnumFunction:MGLTextTransformLowercase type:@encode(MGLTextTransform)]);
+ XCTAssertEqualObjects(gLayer.textLetterSpacing, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.textLineHeight, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.textMaxAngle, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.textMaxWidth, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.textOffset, [MGLRuntimeStylingHelper testOffsetFunction]);
- XCTAssertEqualObjects(gLayer.textAllowOverlap, [MGLRuntimeStylingHelper testBoolFunction]);
- XCTAssertEqualObjects(gLayer.textIgnorePlacement, [MGLRuntimeStylingHelper testBoolFunction]);
XCTAssertEqualObjects(gLayer.textOptional, [MGLRuntimeStylingHelper testBoolFunction]);
- XCTAssertEqualObjects(gLayer.iconOpacity, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.textPadding, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.textPitchAlignment, [MGLRuntimeStylingHelper testEnumFunction:MGLTextPitchAlignmentAuto type:@encode(MGLTextPitchAlignment)]);
+ XCTAssertEqualObjects(gLayer.textRotate, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.textRotationAlignment, [MGLRuntimeStylingHelper testEnumFunction:MGLTextRotationAlignmentAuto type:@encode(MGLTextRotationAlignment)]);
+ XCTAssertEqualObjects(gLayer.textSize, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.textTransform, [MGLRuntimeStylingHelper testEnumFunction:MGLTextTransformLowercase type:@encode(MGLTextTransform)]);
XCTAssertEqualObjects(gLayer.iconColor, [MGLRuntimeStylingHelper testColorFunction]);
+ XCTAssertEqualObjects(gLayer.iconHaloBlur, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.iconHaloColor, [MGLRuntimeStylingHelper testColorFunction]);
XCTAssertEqualObjects(gLayer.iconHaloWidth, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.iconHaloBlur, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.iconOpacity, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.iconTranslate, [MGLRuntimeStylingHelper testOffsetFunction]);
XCTAssertEqualObjects(gLayer.iconTranslateAnchor, [MGLRuntimeStylingHelper testEnumFunction:MGLIconTranslateAnchorViewport type:@encode(MGLIconTranslateAnchor)]);
- XCTAssertEqualObjects(gLayer.textOpacity, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.textColor, [MGLRuntimeStylingHelper testColorFunction]);
+ XCTAssertEqualObjects(gLayer.textHaloBlur, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.textHaloColor, [MGLRuntimeStylingHelper testColorFunction]);
XCTAssertEqualObjects(gLayer.textHaloWidth, [MGLRuntimeStylingHelper testNumberFunction]);
- XCTAssertEqualObjects(gLayer.textHaloBlur, [MGLRuntimeStylingHelper testNumberFunction]);
+ XCTAssertEqualObjects(gLayer.textOpacity, [MGLRuntimeStylingHelper testNumberFunction]);
XCTAssertEqualObjects(gLayer.textTranslate, [MGLRuntimeStylingHelper testOffsetFunction]);
XCTAssertEqualObjects(gLayer.textTranslateAnchor, [MGLRuntimeStylingHelper testEnumFunction:MGLTextTranslateAnchorViewport type:@encode(MGLTextTranslateAnchor)]);
}
diff --git a/platform/default/resources/star_tilestream_net.der b/platform/default/resources/star_tilestream_net.der
deleted file mode 100644
index 3c7cea0ff7..0000000000
--- a/platform/default/resources/star_tilestream_net.der
+++ /dev/null
Binary files differ
diff --git a/platform/ios/CHANGELOG.md b/platform/ios/CHANGELOG.md
index 99707e0c2d..a9760532ad 100644
--- a/platform/ios/CHANGELOG.md
+++ b/platform/ios/CHANGELOG.md
@@ -4,6 +4,10 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
## master
+* Improved the line wrapping behavior of point-placed labels written in Chinese, Japanese, and Yi. ([#6828](https://github.com/mapbox/mapbox-gl-native/pull/6828))
+
+## 3.4.0
+
### Packaging
* Xcode 7.3 or above is required for using this SDK. ([#6059](https://github.com/mapbox/mapbox-gl-native/issues/6059))
@@ -21,7 +25,6 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* TileJSON manifests can now specify `"scheme": "tms"` to indicate the use of [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) coordinates. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270))
* Fixed an issue causing abstract MGLMultiPointFeature objects to be returned in feature query results. Now concrete MGLPointCollectionFeature objects are returned. ([#6742](https://github.com/mapbox/mapbox-gl-native/pull/6742))
* Fixed rendering artifacts and missing glyphs that occurred after viewing a large number of CJK characters on the map. ([#5908](https://github.com/mapbox/mapbox-gl-native/pull/5908))
-* Improved the line wrapping behavior of point-placed labels written in Chinese, Japanese, and Yi. ([#6828](https://github.com/mapbox/mapbox-gl-native/pull/6828))
* `-[MGLMapView resetPosition]` now resets to the current style’s default center coordinates, zoom level, direction, and pitch, if specified. ([#6127](https://github.com/mapbox/mapbox-gl-native/pull/6127))
* Fixed an issue where feature querying sometimes failed to return the expected features when the map was tilted. ([#6773](https://github.com/mapbox/mapbox-gl-native/pull/6773))
* MGLFeature’s `attributes` and `identifier` properties are now writable. ([#6728](https://github.com/mapbox/mapbox-gl-native/pull/6728))
@@ -42,14 +45,15 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* The user dot now animates between user locations when user tracking is disabled. ([#6215](https://github.com/mapbox/mapbox-gl-native/pull/6215))
* To customize the appearance of the user location annotation, subclass the newly added MGLUserLocationAnnotationView class and implement `-[MGLMapViewDelegate mapView:viewForAnnotation:]`. ([#5882](https://github.com/mapbox/mapbox-gl-native/pull/5882))
+* `-[MGLMapView viewForAnnotation:]` now returns the user location annotation view when given the user location annotation. ([#6957](https://github.com/mapbox/mapbox-gl-native/pull/6957))
* Fixed an issue causing the user dot’s accuracy ring to wobble while zooming in and out. ([#6019](https://github.com/mapbox/mapbox-gl-native/pull/6019))
* Heading accuracy indicator sizing has been changed to appear more precise. ([#6120](https://github.com/mapbox/mapbox-gl-native/pull/6120))
* Fixed an issue that caused the map to not update to reflect the centerOffset when the user location was tracked. ([#6216](https://github.com/mapbox/mapbox-gl-native/pull/6216))
### Annotations
-* MGLPolyline annotations and the exterior coordinates of MGLPolygon annotations are now able to be mutated, part or all, and changes are displayed immediately. ([#6565](https://github.com/mapbox/mapbox-gl-native/pull/6565))
-* Added new APIs to MGLMapView to query for visible annotations. Combined with `-[MGLMapView viewForAnnotation:]`, these APIs can be used to access all visible annotation views. ([6061](https://github.com/mapbox/mapbox-gl-native/pull/6061))
+* Added new methods to MGLMultiPoint for changing or appending vertices along polyline annotations and the exteriors of polygon annotations. ([#6565](https://github.com/mapbox/mapbox-gl-native/pull/6565))
+* Added new APIs to MGLMapView to query for visible annotations. Combined with `-[MGLMapView viewForAnnotation:]`, these APIs can be used to access all visible annotation views. ([6061](https://github.com/mapbox/mapbox-gl-native/pull/6061))
* Fixed an issue causing offscreen annotation views to be updated even when they were in the reuse queue. ([#5987](https://github.com/mapbox/mapbox-gl-native/pull/5987))
* Fixed an issue preventing MGLAnnotationView from animating when its coordinate changes. ([#6215](https://github.com/mapbox/mapbox-gl-native/pull/6215))
* Fixed an issue causing the wrong annotation view to be selected when tapping an annotation view with a center offset applied. ([#5931](https://github.com/mapbox/mapbox-gl-native/pull/5931))
@@ -57,6 +61,7 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
* Per documentation, the first and last coordinates in an MGLPolygon must be identical in order for the polygon to draw correctly. The same is true for an MGLPolygon’s interior polygon. ([#5514](https://github.com/mapbox/mapbox-gl-native/pull/5514))
* To make an MGLPolyline or MGLPolygon span the antimeridian, specify coordinates with longitudes greater than 180° or less than −180°. ([#6088](https://github.com/mapbox/mapbox-gl-native/pull/6088))
* Deprecated `-[MGLMapViewDelegate mapView:alphaForShapeAnnotation:]` in favor of specifying an alpha component via `-[MGLMapViewDelegate mapView:strokeColorForShapeAnnotation:]` or `-[MGLMapViewDelegate mapView:fillColorForPolygonAnnotation:]`. ([#6706](https://github.com/mapbox/mapbox-gl-native/pull/6706))
+* Various method arguments that are represented as C arrays of `CLLocationCoordinate2D` instances have been marked `const` to streamline bridging to Swift. ([#7215](https://github.com/mapbox/mapbox-gl-native/pull/7215))
* Fixed an issue that caused an annotation view to disappear if it isn’t created using the annotation view reuse queue. ([#6485](https://github.com/mapbox/mapbox-gl-native/pull/6485))
* Fixed an issue that could reset user-added transformations on annotation views. ([#6166](https://github.com/mapbox/mapbox-gl-native/pull/6166))
* Improved the performance of relocating a non-view-backed point annotation by changing its `coordinate` property. ([#5385](https://github.com/mapbox/mapbox-gl-native/pull/5385))
@@ -77,10 +82,27 @@ Mapbox welcomes participation and contributions from everyone. Please read [CONT
### Other changes
* Raster tiles such as those from Mapbox Satellite are now cached, eliminating flashing while panning back and forth. ([#7091](https://github.com/mapbox/mapbox-gl-native/pull/7091))
+* Improved the performance of symbol style layers. ([#7025](https://github.com/mapbox/mapbox-gl-native/pull/7025))
* As the user zooms in, tiles from lower zoom levels are scaled up until tiles for higher zoom levels are loaded. ([#5143](https://github.com/mapbox/mapbox-gl-native/pull/5143))
* Notification names and user info keys are now string enumeration values for ease of use in Swift. ([#6794](https://github.com/mapbox/mapbox-gl-native/pull/6794))
* MGLMapDebugOverdrawVisualizationMask no longer has any effect in Release builds of the SDK. This debug mask has been disabled for performance reasons. ([#5555](https://github.com/mapbox/mapbox-gl-native/pull/5555))
* Fixed a typo in the documentation for the MGLCompassDirectionFormatter class. ([#5879](https://github.com/mapbox/mapbox-gl-native/pull/5879))
+* The UITapGestureRecognizer on MGLMapView that is used for selecting annotations now fails if a tap does not select an annotation. ([#7246](https://github.com/mapbox/mapbox-gl-native/pull/7246))
+
+## 3.3.7 - November 17, 2016
+
+* This version is the same as 3.3.6 but it is built with Xcode 8 that produces a smaller binary. Developers using this version in Swift applications built with Xcode 7.3.1 should use the unstripped, `*-symbols` framework.
+
+## 3.3.6 - November 9, 2016
+
+* Fixed a crash that occurred during low-memory situations when multiple instances of MGLMapView were in the view hierarchy. The speculative fix in v3.3.5 has been reverted. ([#6972](https://github.com/mapbox/mapbox-gl-native/pull/6972))
+
+## 3.3.5 - November 2, 2016
+
+* Speculatively fixed an OpenGL rendering crash. ([#6844](https://github.com/mapbox/mapbox-gl-native/pull/6844))
+* Fixed an issue with symbols not being properly stripped from the dynamic framework. The dSYM file included with the standard dynamic framework in previous releases (e.g., `mapbox-ios-sdk-3.3.4-dynamic.zip` or the `Mapbox-iOS-SDK` pod) could not be used to symbolicate crashes. ([#6531](https://github.com/mapbox/mapbox-gl-native/pull/6531))
+* Include simulator architecture slices in the dSYM file that is generated for release builds. ([#5740](https://github.com/mapbox/mapbox-gl-native/pull/5740))
+* Fixed a rare networking-related crash. ([#5932](https://github.com/mapbox/mapbox-gl-native/pull/5932))
## 3.3.7 - November 17, 2016
diff --git a/platform/ios/DEVELOPING.md b/platform/ios/DEVELOPING.md
index a948456203..94ff49ee1b 100644
--- a/platform/ios/DEVELOPING.md
+++ b/platform/ios/DEVELOPING.md
@@ -109,6 +109,15 @@ To add or update text that the user may see in the iOS SDK:
1. _(Optional.)_ When dealing with a number followed by a pluralized word, do not split the string. Instead, use a format string and make `val` ambiguous, like `%d file(s)`. Then pluralize for English in the appropriate [.stringsdict file](https://developer.apple.com/library/ios/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html). See [platform/darwin/resources/en.lproj/Foundation.stringsdict](../darwin/resources/en.lproj/Foundation.stringsdict) for an example. Localizers should do likewise for their languages.
1. Run `make genstrings` and commit any changes it makes to .strings files. The make rule also updates the macOS SDK’s strings tables.
+### Adding a localization
+
+To add a localization to the iOS SDK:
+
+1. In ios.xcworkspace, open the project editor for ios.xcodeproj. Using the project editor’s sidebar or tab bar dropdown, go to the “ios” project; under the Localizations section of the Info tab, click the + button to add your language to the project.
+1. In the sheet that appears, select all the .strings and .stringsdict files but not the .storyboard file. (LaunchScreen.storyboard is part of the iosapp example application, which is not localized.)
+1. In the Project navigator, expand each .strings and .stringsdict file in the project. An additional version for your localization should be listed; translate it. Translate everything on the right side of the equals sign. Leave the left side and any comments unmodified. See Apple’s documentation on the [.strings](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/LoadingResources/Strings/Strings.html) and [.stringsdict](https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html) formats.
+1. You’re already most of the way towards localizing the macOS SDK too – consider [completing that localization](../macos/DEVELOPING.md#adding-a-localization).
+
## Testing
`make ios-test` builds and runs unit tests of cross-platform code as well as the SDK.
diff --git a/platform/ios/Mapbox-iOS-SDK-symbols.podspec b/platform/ios/Mapbox-iOS-SDK-symbols.podspec
index e26de7915f..3ec0fb3876 100644
--- a/platform/ios/Mapbox-iOS-SDK-symbols.podspec
+++ b/platform/ios/Mapbox-iOS-SDK-symbols.podspec
@@ -1,7 +1,7 @@
Pod::Spec.new do |m|
m.name = 'Mapbox-iOS-SDK'
- m.version = '3.4.0-beta.2-symbols'
+ m.version = '3.4.0-beta.4-symbols'
m.summary = 'Open source vector map solution for iOS with full styling capabilities.'
m.description = 'Open source, OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa Touch APIs.'
diff --git a/platform/ios/Mapbox-iOS-SDK.podspec b/platform/ios/Mapbox-iOS-SDK.podspec
index 6fd6d4b46f..be63221878 100644
--- a/platform/ios/Mapbox-iOS-SDK.podspec
+++ b/platform/ios/Mapbox-iOS-SDK.podspec
@@ -1,7 +1,7 @@
Pod::Spec.new do |m|
m.name = 'Mapbox-iOS-SDK'
- m.version = '3.4.0-beta.2'
+ m.version = '3.4.0-beta.4'
m.summary = 'Open source vector map solution for iOS with full styling capabilities.'
m.description = 'Open source, OpenGL-based vector map solution for iOS with full styling capabilities and Cocoa Touch APIs.'
diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m
index a7ea429300..8a2ccee413 100644
--- a/platform/ios/app/MBXViewController.m
+++ b/platform/ios/app/MBXViewController.m
@@ -71,6 +71,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsRuntimeStylingRows) {
MBXSettingsRuntimeStylingVectorSource,
MBXSettingsRuntimeStylingRasterSource,
MBXSettingsRuntimeStylingCountryLabels,
+ MBXSettingsRuntimeStylingRouteLine,
};
typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@@ -332,6 +333,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
@"Style Vector Source",
@"Style Raster Source",
[NSString stringWithFormat:@"Label Countries in %@", (_usingLocaleBasedCountryLabels ? @"Local Language" : [[NSLocale currentLocale] displayNameForKey:NSLocaleIdentifier value:[self bestLanguageForUser]])],
+ @"Add Route Line",
]];
break;
case MBXSettingsMiscellaneous:
@@ -490,6 +492,9 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
case MBXSettingsRuntimeStylingCountryLabels:
[self styleCountryLabelsLanguage];
break;
+ case MBXSettingsRuntimeStylingRouteLine:
+ [self styleRouteLine];
+ break;
default:
NSAssert(NO, @"All runtime styling setting rows should be implemented");
break;
@@ -769,6 +774,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
MGLFillStyleLayer *fillLayer = [[MGLFillStyleLayer alloc] initWithIdentifier:@"test" source:source];
fillLayer.fillColor = [MGLStyleValue<UIColor *> valueWithRawValue:[UIColor purpleColor]];
[self.mapView.style addLayer:fillLayer];
+
}
- (void)styleSymbolLayer
@@ -815,6 +821,18 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
});
}
++ (MGLStyleConstantValue<NSValue *> *)testEnum:(NSUInteger)value type:(const char *)type
+{
+ return [MGLStyleConstantValue<NSValue *> valueWithRawValue:[NSValue value:&value withObjCType:type]];
+}
+
++ (MGLStyleFunction<NSValue *> *)testEnumFunction:(NSUInteger)value type:(const char *)type
+{
+ return [MGLStyleFunction<NSValue *> valueWithStops:@{
+ @18: [self testEnum:value type:type],
+ }];
+}
+
- (void)styleFilteredLines
{
// set style and focus on lower 48
@@ -1080,6 +1098,44 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
[self styleLabelLanguageForLayersNamed:labelLayers];
}
+- (void)styleRouteLine
+{
+ CLLocationCoordinate2D coords[] = {
+ { 43.84455590478528, 10.504238605499268 },
+ { 43.84385562343126, 10.504125952720642 },
+ { 43.84388657526694, 10.503299832344055 },
+ { 43.84332557075269, 10.503235459327698 },
+ { 43.843441641085036, 10.502264499664307 },
+ { 43.84396395478592, 10.50242006778717 },
+ { 43.84406067904351, 10.501744151115416 },
+ { 43.84422317544319, 10.501792430877686 }
+ };
+ NSInteger count = sizeof(coords) / sizeof(coords[0]);
+
+ [self.mapView setCenterCoordinate:coords[0] zoomLevel:16 animated:YES];
+
+ MGLPolylineFeature *routeLine = [MGLPolylineFeature polylineWithCoordinates:coords count:count];
+
+ MGLGeoJSONSource *routeSource = [[MGLGeoJSONSource alloc] initWithIdentifier:@"style-route-source" features:@[routeLine] options:nil];
+ [self.mapView.style addSource:routeSource];
+
+ MGLLineStyleLayer *baseRouteLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"style-base-route-layer" source:routeSource];
+ baseRouteLayer.lineColor = [MGLStyleConstantValue valueWithRawValue:[UIColor orangeColor]];
+ baseRouteLayer.lineWidth = [MGLStyleConstantValue valueWithRawValue:@20];
+ baseRouteLayer.lineOpacity = [MGLStyleConstantValue valueWithRawValue:@0.5];
+ baseRouteLayer.lineCap = [MGLStyleConstantValue valueWithRawValue:[NSValue valueWithMGLLineCap:MGLLineCapRound]];
+ baseRouteLayer.lineJoin = [MGLStyleConstantValue valueWithRawValue:[NSValue valueWithMGLLineJoin:MGLLineJoinRound]];
+ [self.mapView.style addLayer:baseRouteLayer];
+
+ MGLLineStyleLayer *routeLayer = [[MGLLineStyleLayer alloc] initWithIdentifier:@"style-base-route-layer" source:routeSource];
+ routeLayer.lineColor = [MGLStyleConstantValue valueWithRawValue:[UIColor whiteColor]];
+ routeLayer.lineWidth = [MGLStyleConstantValue valueWithRawValue:@15];
+ routeLayer.lineOpacity = [MGLStyleConstantValue valueWithRawValue:@0.8];
+ routeLayer.lineCap = [MGLStyleConstantValue valueWithRawValue:[NSValue valueWithMGLLineCap:MGLLineCapRound]];
+ routeLayer.lineJoin = [MGLStyleConstantValue valueWithRawValue:[NSValue valueWithMGLLineJoin:MGLLineJoinRound]];
+ [self.mapView.style addLayer:routeLayer];
+}
+
- (void)styleLabelLanguageForLayersNamed:(NSArray<NSString *> *)layers
{
_usingLocaleBasedCountryLabels = !_usingLocaleBasedCountryLabels;
@@ -1540,7 +1596,7 @@ typedef NS_ENUM(NSInteger, MBXSettingsMiscellaneousRows) {
{
queuedAnnotations += queue.count;
}
- self.hudLabel.text = [NSString stringWithFormat:@"Visible: %ld Queued: %ld", (long)mapView.visibleAnnotations.count, (long)queuedAnnotations];
+ self.hudLabel.text = [NSString stringWithFormat:@"Visible: %ld Queued: %ld", (unsigned long)mapView.visibleAnnotations.count, (unsigned long)queuedAnnotations];
}
}
diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj
index e8e246907a..2dcfd71216 100644
--- a/platform/ios/ios.xcodeproj/project.pbxproj
+++ b/platform/ios/ios.xcodeproj/project.pbxproj
@@ -127,6 +127,10 @@
4018B1C91CDC288A00F666AF /* MGLAnnotationView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4018B1C31CDC277F00F666AF /* MGLAnnotationView_Private.h */; };
4018B1CA1CDC288E00F666AF /* MGLAnnotationView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4018B1C51CDC277F00F666AF /* MGLAnnotationView.h */; settings = {ATTRIBUTES = (Public, ); }; };
4018B1CB1CDC288E00F666AF /* MGLAnnotationView.h in Headers */ = {isa = PBXBuildFile; fileRef = 4018B1C51CDC277F00F666AF /* MGLAnnotationView.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4032C5BF1DE1FC780062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4032C5B81DE1EE7D0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4032C5C01DE1FC780062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4032C5B81DE1EE7D0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4032C5C11DE1FC7E0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4032C5BD1DE1FC690062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm */; };
+ 4032C5C21DE1FC7E0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4032C5BD1DE1FC690062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm */; };
404326891D5B9B27007111BD /* MGLAnnotationContainerView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404326881D5B9B1A007111BD /* MGLAnnotationContainerView_Private.h */; };
4049C29D1DB6CD6C00B3F799 /* MGLPointCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 4049C29B1DB6CD6C00B3F799 /* MGLPointCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
4049C29E1DB6CD6C00B3F799 /* MGLPointCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 4049C29B1DB6CD6C00B3F799 /* MGLPointCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
@@ -139,7 +143,13 @@
404C26E51D89B877000AA13D /* MGLTileSet.mm in Sources */ = {isa = PBXBuildFile; fileRef = 404C26E11D89B877000AA13D /* MGLTileSet.mm */; };
404C26E71D89C55D000AA13D /* MGLTileSet_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E61D89C515000AA13D /* MGLTileSet_Private.h */; };
404C26E81D89C55D000AA13D /* MGLTileSet_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 404C26E61D89C515000AA13D /* MGLTileSet_Private.h */; };
+ 40599F0C1DEE1B7600182B5D /* api_mapbox_staging.der in Resources */ = {isa = PBXBuildFile; fileRef = 40599F001DEE1B2400182B5D /* api_mapbox_staging.der */; };
+ 40599F0D1DEE1B7A00182B5D /* api_mapbox_com-digicert.der in Resources */ = {isa = PBXBuildFile; fileRef = 40599F011DEE1B2400182B5D /* api_mapbox_com-digicert.der */; };
+ 40599F0E1DEE1B7E00182B5D /* api_mapbox_com-geotrust.der in Resources */ = {isa = PBXBuildFile; fileRef = 40599F021DEE1B2400182B5D /* api_mapbox_com-geotrust.der */; };
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.der in Resources */ = {isa = PBXBuildFile; fileRef = 40599F011DEE1B2400182B5D /* api_mapbox_com-digicert.der */; };
+ 408982EB1DEE209100754016 /* api_mapbox_com-geotrust.der in Resources */ = {isa = PBXBuildFile; fileRef = 40599F021DEE1B2400182B5D /* api_mapbox_com-geotrust.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 */; };
@@ -161,7 +171,6 @@
7E016D851D9E890300A29A21 /* MGLPolygon+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */; };
7E016D861D9E890300A29A21 /* MGLPolygon+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */; };
7E016D871D9E890300A29A21 /* MGLPolygon+MGLAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */; };
- 92BE56771DEDD44500A4F2B6 /* MGLSourceTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 92BE56761DEDD44500A4F2B6 /* MGLSourceTests.m */; };
DA0CD5901CF56F6A00A5F5A5 /* MGLFeatureTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */; };
DA17BE301CC4BAC300402C41 /* MGLMapView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */; };
DA17BE311CC4BDAA00402C41 /* MGLMapView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */; };
@@ -181,7 +190,7 @@
DA25D5CD1CCDA11500607828 /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = DA25D5B91CCD9EDE00607828 /* Settings.bundle */; };
DA27C24E1CBB3811000B0ECD /* GLKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA27C24D1CBB3811000B0ECD /* GLKit.framework */; };
DA27C24F1CBB4C11000B0ECD /* MGLAccountManager_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8847FF1CBAFA6200AB86E3 /* MGLAccountManager_Private.h */; };
- DA2DBBCE1D51E80400D38FF9 /* MGLMapViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2DBBCD1D51E80400D38FF9 /* MGLMapViewTests.m */; };
+ DA2DBBCE1D51E80400D38FF9 /* MGLStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2DBBCD1D51E80400D38FF9 /* MGLStyleLayerTests.m */; };
DA2E88561CC036F400F24E7B /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA8847D21CBAF91600AB86E3 /* Mapbox.framework */; };
DA2E88611CC0382C00F24E7B /* MGLGeometryTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA2E885C1CC0382C00F24E7B /* MGLGeometryTests.mm */; };
DA2E88621CC0382C00F24E7B /* MGLOfflinePackTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2E885D1CC0382C00F24E7B /* MGLOfflinePackTests.m */; };
@@ -289,9 +298,6 @@
DA8848731CBAFCC100AB86E3 /* mapbox.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848691CBAFCC100AB86E3 /* mapbox.png */; };
DA8848741CBAFCC100AB86E3 /* mapbox@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA88486A1CBAFCC100AB86E3 /* mapbox@2x.png */; };
DA8848751CBAFCC100AB86E3 /* mapbox@3x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA88486B1CBAFCC100AB86E3 /* mapbox@3x.png */; };
- DA88487A1CBAFD5C00AB86E3 /* api_mapbox_com-digicert.der in Resources */ = {isa = PBXBuildFile; fileRef = DA8848771CBAFD5C00AB86E3 /* api_mapbox_com-digicert.der */; };
- DA88487B1CBAFD5C00AB86E3 /* api_mapbox_com-geotrust.der in Resources */ = {isa = PBXBuildFile; fileRef = DA8848781CBAFD5C00AB86E3 /* api_mapbox_com-geotrust.der */; };
- DA88487C1CBAFD5C00AB86E3 /* star_tilestream_net.der in Resources */ = {isa = PBXBuildFile; fileRef = DA8848791CBAFD5C00AB86E3 /* star_tilestream_net.der */; };
DA8848841CBB033F00AB86E3 /* FABAttributes.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848801CBB033F00AB86E3 /* FABAttributes.h */; };
DA8848851CBB033F00AB86E3 /* FABKitProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848811CBB033F00AB86E3 /* FABKitProtocol.h */; };
DA8848861CBB033F00AB86E3 /* Fabric+FABKits.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8848821CBB033F00AB86E3 /* Fabric+FABKits.h */; };
@@ -304,9 +310,6 @@
DA8933BF1CCD2CAD00E68420 /* Foundation.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DA8933BD1CCD2CAD00E68420 /* Foundation.stringsdict */; };
DA8933DB1CCD31D400E68420 /* Foundation.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA8933BA1CCD2CA100E68420 /* Foundation.strings */; };
DA8933DC1CCD31D400E68420 /* Foundation.stringsdict in Resources */ = {isa = PBXBuildFile; fileRef = DA8933BD1CCD2CAD00E68420 /* Foundation.stringsdict */; };
- DA8933DD1CCD31D400E68420 /* api_mapbox_com-digicert.der in Resources */ = {isa = PBXBuildFile; fileRef = DA8848771CBAFD5C00AB86E3 /* api_mapbox_com-digicert.der */; };
- DA8933DE1CCD31D400E68420 /* api_mapbox_com-geotrust.der in Resources */ = {isa = PBXBuildFile; fileRef = DA8848781CBAFD5C00AB86E3 /* api_mapbox_com-geotrust.der */; };
- DA8933DF1CCD31D400E68420 /* star_tilestream_net.der in Resources */ = {isa = PBXBuildFile; fileRef = DA8848791CBAFD5C00AB86E3 /* star_tilestream_net.der */; };
DA8933E01CCD31DF00E68420 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DA89339F1CCC951200E68420 /* Localizable.strings */; };
DA8933E11CCD31DF00E68420 /* Compass.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848631CBAFCC100AB86E3 /* Compass.png */; };
DA8933E21CCD31DF00E68420 /* Compass@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DA8848641CBAFCC100AB86E3 /* Compass@2x.png */; };
@@ -561,6 +564,10 @@
4018B1C41CDC277F00F666AF /* MGLAnnotationView.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLAnnotationView.mm; sourceTree = "<group>"; };
4018B1C51CDC277F00F666AF /* MGLAnnotationView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationView.h; sourceTree = "<group>"; };
402E9DE01CD2C76200FD4519 /* Mapbox.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Mapbox.playground; sourceTree = "<group>"; };
+ 4032C5B71DE1EBB90062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = "NSValue+MGLStyleEnumAttributeAdditions.h.ejs"; sourceTree = "<group>"; };
+ 4032C5B81DE1EE7D0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSValue+MGLStyleEnumAttributeAdditions.h"; sourceTree = "<group>"; };
+ 4032C5BC1DE1FAFC0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = "NSValue+MGLStyleEnumAttributeAdditions.mm.ejs"; sourceTree = "<group>"; };
+ 4032C5BD1DE1FC690062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSValue+MGLStyleEnumAttributeAdditions.mm"; sourceTree = "<group>"; };
404326881D5B9B1A007111BD /* MGLAnnotationContainerView_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationContainerView_Private.h; sourceTree = "<group>"; };
4049C29B1DB6CD6C00B3F799 /* MGLPointCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLPointCollection.h; sourceTree = "<group>"; };
4049C29C1DB6CD6C00B3F799 /* MGLPointCollection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLPointCollection.mm; sourceTree = "<group>"; };
@@ -568,6 +575,9 @@
404C26E01D89B877000AA13D /* MGLTileSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLTileSet.h; sourceTree = "<group>"; };
404C26E11D89B877000AA13D /* MGLTileSet.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLTileSet.mm; sourceTree = "<group>"; };
404C26E61D89C515000AA13D /* MGLTileSet_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLTileSet_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.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = "api_mapbox_com-digicert.der"; sourceTree = "<group>"; };
+ 40599F021DEE1B2400182B5D /* api_mapbox_com-geotrust.der */ = {isa = PBXFileReference; lastKnownFileType = file; path = "api_mapbox_com-geotrust.der"; sourceTree = "<group>"; };
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>"; };
@@ -585,7 +595,6 @@
7E016D7D1D9E86BE00A29A21 /* MGLPolyline+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLPolyline+MGLAdditions.m"; sourceTree = "<group>"; };
7E016D821D9E890300A29A21 /* MGLPolygon+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLPolygon+MGLAdditions.h"; sourceTree = "<group>"; };
7E016D831D9E890300A29A21 /* MGLPolygon+MGLAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "MGLPolygon+MGLAdditions.m"; sourceTree = "<group>"; };
- 92BE56761DEDD44500A4F2B6 /* MGLSourceTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLSourceTests.m; sourceTree = "<group>"; };
DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFeatureTests.mm; path = ../../darwin/test/MGLFeatureTests.mm; sourceTree = "<group>"; };
DA17BE2F1CC4BAC300402C41 /* MGLMapView_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLMapView_Private.h; sourceTree = "<group>"; };
DA1DC94A1CB6C1C2006E619F /* Mapbox GL.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Mapbox GL.app"; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -610,8 +619,8 @@
DA25D5BF1CCD9F8400607828 /* Root.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Root.plist; sourceTree = "<group>"; };
DA25D5C51CCDA06800607828 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/Root.strings; sourceTree = "<group>"; };
DA27C24D1CBB3811000B0ECD /* GLKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLKit.framework; path = System/Library/Frameworks/GLKit.framework; sourceTree = SDKROOT; };
- DA2DBBCC1D51E80400D38FF9 /* MGLMapViewTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MGLMapViewTests.h; path = ../../darwin/test/MGLMapViewTests.h; sourceTree = "<group>"; };
- DA2DBBCD1D51E80400D38FF9 /* MGLMapViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLMapViewTests.m; path = ../../darwin/test/MGLMapViewTests.m; sourceTree = "<group>"; };
+ DA2DBBCC1D51E80400D38FF9 /* MGLStyleLayerTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MGLStyleLayerTests.h; path = ../../darwin/test/MGLStyleLayerTests.h; sourceTree = "<group>"; };
+ DA2DBBCD1D51E80400D38FF9 /* MGLStyleLayerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLStyleLayerTests.m; path = ../../darwin/test/MGLStyleLayerTests.m; sourceTree = "<group>"; };
DA2E88511CC036F400F24E7B /* test.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = test.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
DA2E88551CC036F400F24E7B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
DA2E885C1CC0382C00F24E7B /* MGLGeometryTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLGeometryTests.mm; path = ../../darwin/test/MGLGeometryTests.mm; sourceTree = "<group>"; };
@@ -712,9 +721,6 @@
DA8848691CBAFCC100AB86E3 /* mapbox.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = mapbox.png; sourceTree = "<group>"; };
DA88486A1CBAFCC100AB86E3 /* mapbox@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mapbox@2x.png"; sourceTree = "<group>"; };
DA88486B1CBAFCC100AB86E3 /* mapbox@3x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "mapbox@3x.png"; sourceTree = "<group>"; };
- DA8848771CBAFD5C00AB86E3 /* api_mapbox_com-digicert.der */ = {isa = PBXFileReference; lastKnownFileType = file; name = "api_mapbox_com-digicert.der"; path = "../../default/resources/api_mapbox_com-digicert.der"; sourceTree = "<group>"; };
- DA8848781CBAFD5C00AB86E3 /* api_mapbox_com-geotrust.der */ = {isa = PBXFileReference; lastKnownFileType = file; name = "api_mapbox_com-geotrust.der"; path = "../../default/resources/api_mapbox_com-geotrust.der"; sourceTree = "<group>"; };
- DA8848791CBAFD5C00AB86E3 /* star_tilestream_net.der */ = {isa = PBXFileReference; lastKnownFileType = file; name = star_tilestream_net.der; path = ../../default/resources/star_tilestream_net.der; sourceTree = "<group>"; };
DA8848801CBB033F00AB86E3 /* FABAttributes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FABAttributes.h; sourceTree = "<group>"; };
DA8848811CBB033F00AB86E3 /* FABKitProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FABKitProtocol.h; sourceTree = "<group>"; };
DA8848821CBB033F00AB86E3 /* Fabric+FABKits.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Fabric+FABKits.h"; sourceTree = "<group>"; };
@@ -881,6 +887,8 @@
35599DB81D46AD7F0048254D /* Categories */ = {
isa = PBXGroup;
children = (
+ 4032C5B81DE1EE7D0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h */,
+ 4032C5BD1DE1FC690062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm */,
350098DA1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h */,
350098DB1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm */,
);
@@ -892,7 +900,6 @@
children = (
3575798F1D513EF1000B822E /* Layers */,
35B8E08B1D6C8B5100E768D2 /* MGLFilterTests.mm */,
- 92BE56761DEDD44500A4F2B6 /* MGLSourceTests.m */,
DA2207BE1DC0805F0002F84D /* MGLStyleValueTests.swift */,
40CFA64E1D78754A008103BD /* Sources */,
DA2207BD1DC0805F0002F84D /* test-Bridging-Header.h */,
@@ -903,6 +910,8 @@
3575798F1D513EF1000B822E /* Layers */ = {
isa = PBXGroup;
children = (
+ DA2DBBCC1D51E80400D38FF9 /* MGLStyleLayerTests.h */,
+ DA2DBBCD1D51E80400D38FF9 /* MGLStyleLayerTests.m */,
3575797F1D501E09000B822E /* MGLFillStyleLayerTests.m */,
357579821D502AE6000B822E /* MGLRasterStyleLayerTests.m */,
357579841D502AF5000B822E /* MGLSymbolStyleLayerTests.m */,
@@ -1049,8 +1058,6 @@
DA35A2A91CCA058D00E826B2 /* MGLCoordinateFormatterTests.m */,
DA0CD58F1CF56F6A00A5F5A5 /* MGLFeatureTests.mm */,
DA2E885C1CC0382C00F24E7B /* MGLGeometryTests.mm */,
- DA2DBBCC1D51E80400D38FF9 /* MGLMapViewTests.h */,
- DA2DBBCD1D51E80400D38FF9 /* MGLMapViewTests.m */,
35E208A61D24210F00EC9A46 /* MGLNSDataAdditionsTests.m */,
DA2E885D1CC0382C00F24E7B /* MGLOfflinePackTests.m */,
DA2E885E1CC0382C00F24E7B /* MGLOfflineRegionTests.m */,
@@ -1131,9 +1138,6 @@
children = (
DA89339F1CCC951200E68420 /* Localizable.strings */,
DAC49C5F1CD02BC9009E1AA3 /* Localizable.stringsdict */,
- DA8848771CBAFD5C00AB86E3 /* api_mapbox_com-digicert.der */,
- DA8848781CBAFD5C00AB86E3 /* api_mapbox_com-geotrust.der */,
- DA8848791CBAFD5C00AB86E3 /* star_tilestream_net.der */,
DA8848631CBAFCC100AB86E3 /* Compass.png */,
DA8848641CBAFCC100AB86E3 /* Compass@2x.png */,
DA8848651CBAFCC100AB86E3 /* Compass@3x.png */,
@@ -1144,6 +1148,9 @@
DA88486A1CBAFCC100AB86E3 /* mapbox@2x.png */,
DA88486B1CBAFCC100AB86E3 /* mapbox@3x.png */,
DA8933EF1CCD387900E68420 /* strip-frameworks.sh */,
+ 40599F001DEE1B2400182B5D /* api_mapbox_staging.der */,
+ 40599F011DEE1B2400182B5D /* api_mapbox_com-digicert.der */,
+ 40599F021DEE1B2400182B5D /* api_mapbox_com-geotrust.der */,
);
name = "Kit Resources";
path = resources;
@@ -1209,6 +1216,8 @@
DA8F25B91D51D2570010E6B5 /* MGLRuntimeStylingTests.m.ejs */,
DA8F25BA1D51D2570010E6B5 /* MGLStyleLayer.h.ejs */,
DA8F25BB1D51D2570010E6B5 /* MGLStyleLayer.mm.ejs */,
+ 4032C5B71DE1EBB90062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h.ejs */,
+ 4032C5BC1DE1FAFC0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm.ejs */,
);
name = "Foundation Templates";
path = ../../darwin/src;
@@ -1465,6 +1474,7 @@
DA88488B1CBB037E00AB86E3 /* SMCalloutView.h in Headers */,
DA8847FE1CBAFA5100AB86E3 /* MGLTypes.h in Headers */,
DA8847F11CBAFA5100AB86E3 /* MGLGeometry.h in Headers */,
+ 4032C5BF1DE1FC780062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h in Headers */,
DA8848221CBAFA6200AB86E3 /* MGLOfflineRegion_Private.h in Headers */,
35136D4C1D4277FC00C20EFD /* MGLSource.h in Headers */,
3566C76C1D4A8DFA008152BC /* MGLRasterSource.h in Headers */,
@@ -1505,6 +1515,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
+ 4032C5C01DE1FC780062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h in Headers */,
35B82BF91D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h in Headers */,
DA35A2CA1CCAAAD200E826B2 /* NSValue+MGLAdditions.h in Headers */,
350098BC1D480108004B2AF0 /* MGLVectorSource.h in Headers */,
@@ -1805,20 +1816,20 @@
DA8848731CBAFCC100AB86E3 /* mapbox.png in Resources */,
DA8933BC1CCD2CA100E68420 /* Foundation.strings in Resources */,
DA8848741CBAFCC100AB86E3 /* mapbox@2x.png in Resources */,
- DA88487A1CBAFD5C00AB86E3 /* api_mapbox_com-digicert.der in Resources */,
DA8933A31CCC95B000E68420 /* Localizable.strings in Resources */,
DA88486D1CBAFCC100AB86E3 /* Compass.png in Resources */,
DA8848721CBAFCC100AB86E3 /* default_marker@3x.png in Resources */,
- DA88487C1CBAFD5C00AB86E3 /* star_tilestream_net.der in Resources */,
DA88486F1CBAFCC100AB86E3 /* Compass@3x.png in Resources */,
DA88486E1CBAFCC100AB86E3 /* Compass@2x.png in Resources */,
DA8848701CBAFCC100AB86E3 /* default_marker.png in Resources */,
DA8848711CBAFCC100AB86E3 /* default_marker@2x.png in Resources */,
DA8933F01CCD387900E68420 /* strip-frameworks.sh in Resources */,
DA8848751CBAFCC100AB86E3 /* mapbox@3x.png in Resources */,
- DA88487B1CBAFD5C00AB86E3 /* api_mapbox_com-geotrust.der in Resources */,
DAC49C5C1CD02BC9009E1AA3 /* Localizable.stringsdict in Resources */,
DA8933BF1CCD2CAD00E68420 /* Foundation.stringsdict in Resources */,
+ 408982E91DEE208200754016 /* api_mapbox_staging.der in Resources */,
+ 408982EA1DEE208B00754016 /* api_mapbox_com-digicert.der in Resources */,
+ 408982EB1DEE209100754016 /* api_mapbox_com-geotrust.der in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1838,10 +1849,10 @@
DA8933E91CCD31DF00E68420 /* mapbox@3x.png in Resources */,
DA8933DB1CCD31D400E68420 /* Foundation.strings in Resources */,
DA8933DC1CCD31D400E68420 /* Foundation.stringsdict in Resources */,
- DA8933DD1CCD31D400E68420 /* api_mapbox_com-digicert.der in Resources */,
DAC49C5D1CD02BC9009E1AA3 /* Localizable.stringsdict in Resources */,
- DA8933DE1CCD31D400E68420 /* api_mapbox_com-geotrust.der in Resources */,
- DA8933DF1CCD31D400E68420 /* star_tilestream_net.der in Resources */,
+ 40599F0C1DEE1B7600182B5D /* api_mapbox_staging.der in Resources */,
+ 40599F0D1DEE1B7A00182B5D /* api_mapbox_com-digicert.der in Resources */,
+ 40599F0E1DEE1B7E00182B5D /* api_mapbox_com-geotrust.der in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1884,7 +1895,7 @@
DA2E88611CC0382C00F24E7B /* MGLGeometryTests.mm in Sources */,
357579801D501E09000B822E /* MGLFillStyleLayerTests.m in Sources */,
DA2E88641CC0382C00F24E7B /* MGLOfflineStorageTests.m in Sources */,
- DA2DBBCE1D51E80400D38FF9 /* MGLMapViewTests.m in Sources */,
+ DA2DBBCE1D51E80400D38FF9 /* MGLStyleLayerTests.m in Sources */,
DA35A2C61CCA9F8300E826B2 /* MGLCompassDirectionFormatterTests.m in Sources */,
3575798E1D502EC7000B822E /* MGLRuntimeStylingHelper.m in Sources */,
4085AF091D933DEA00F11B22 /* MGLTileSetTests.mm in Sources */,
@@ -1902,7 +1913,6 @@
357579831D502AE6000B822E /* MGLRasterStyleLayerTests.m in Sources */,
353D23961D0B0DFE002BE09D /* MGLAnnotationViewTests.m in Sources */,
35E208A71D24210F00EC9A46 /* MGLNSDataAdditionsTests.m in Sources */,
- 92BE56771DEDD44500A4F2B6 /* MGLSourceTests.m in Sources */,
DA0CD5901CF56F6A00A5F5A5 /* MGLFeatureTests.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1966,6 +1976,7 @@
DA8848301CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.m in Sources */,
353AFA161D65AB17005A69F4 /* NSDate+MGLAdditions.mm in Sources */,
35D13AC51D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm in Sources */,
+ 4032C5C11DE1FC7E0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm in Sources */,
DA8848241CBAFA6200AB86E3 /* MGLOfflineStorage.mm in Sources */,
DA88482A1CBAFA6200AB86E3 /* MGLTilePyramidOfflineRegion.mm in Sources */,
4049C29F1DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */,
@@ -2038,6 +2049,7 @@
DAA4E4231CBB730400178DFB /* MGLPolygon.mm in Sources */,
353AFA171D65AB17005A69F4 /* NSDate+MGLAdditions.mm in Sources */,
35D13AC61D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm in Sources */,
+ 4032C5C21DE1FC7E0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm in Sources */,
DAA4E42A1CBB730400178DFB /* NSProcessInfo+MGLAdditions.m in Sources */,
DAA4E4211CBB730400178DFB /* MGLOfflineStorage.mm in Sources */,
4049C2A01DB6CD6C00B3F799 /* MGLPointCollection.mm in Sources */,
diff --git a/platform/ios/ios.xcworkspace/contents.xcworkspacedata b/platform/ios/ios.xcworkspace/contents.xcworkspacedata
index 08503d2be1..65d928a67d 100644
--- a/platform/ios/ios.xcworkspace/contents.xcworkspacedata
+++ b/platform/ios/ios.xcworkspace/contents.xcworkspacedata
@@ -11,6 +11,9 @@
location = "group:uitest/KIF/KIF.xcodeproj">
</FileRef>
<FileRef
+ location = "group:uitest/OHHTTPStubs/OHHTTPStubs/OHHTTPStubs.xcodeproj">
+ </FileRef>
+ <FileRef
location = "group:../../build/ios/mbgl.xcodeproj">
</FileRef>
</Workspace>
diff --git a/platform/default/resources/api_mapbox_com-digicert.der b/platform/ios/resources/api_mapbox_com-digicert.der
index e8ef427f33..e8ef427f33 100644
--- a/platform/default/resources/api_mapbox_com-digicert.der
+++ b/platform/ios/resources/api_mapbox_com-digicert.der
Binary files differ
diff --git a/platform/default/resources/api_mapbox_com-geotrust.der b/platform/ios/resources/api_mapbox_com-geotrust.der
index 1c7331dedc..1c7331dedc 100644
--- a/platform/default/resources/api_mapbox_com-geotrust.der
+++ b/platform/ios/resources/api_mapbox_com-geotrust.der
Binary files differ
diff --git a/platform/ios/resources/api_mapbox_staging.der b/platform/ios/resources/api_mapbox_staging.der
new file mode 100644
index 0000000000..45f7df7c49
--- /dev/null
+++ b/platform/ios/resources/api_mapbox_staging.der
Binary files differ
diff --git a/platform/ios/src/MGLAPIClient.m b/platform/ios/src/MGLAPIClient.m
index b9b0dc17cc..7fb6538e5d 100644
--- a/platform/ios/src/MGLAPIClient.m
+++ b/platform/ios/src/MGLAPIClient.m
@@ -122,7 +122,7 @@ static NSString * const MGLAPIClientHTTPMethodPost = @"POST";
self.geoTrustCert = certificate;
[self loadCertificate:&certificate withResource:@"api_mapbox_com-digicert"];
self.digicertCert = certificate;
- [self loadCertificate:&certificate withResource:@"star_tilestream_net"];
+ [self loadCertificate:&certificate withResource:@"api_mapbox_staging"];
self.testServerCert = certificate;
}
diff --git a/platform/ios/src/MGLMapView.h b/platform/ios/src/MGLMapView.h
index e467495a4a..771a48c7ff 100644
--- a/platform/ios/src/MGLMapView.h
+++ b/platform/ios/src/MGLMapView.h
@@ -118,6 +118,21 @@ IB_DESIGNABLE
#pragma mark Configuring the Map’s Appearance
/**
+ The style currently displayed in the receiver.
+
+ Unlike the `styleURL` property, this property is set to an object that allows
+ you to manipulate every aspect of the style locally.
+
+ @note The default styles provided by Mapbox contain sources and layers with
+ identifiers that will change over time. Applications that use APIs that
+ manipulate a style's sources and layers must first set the 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`.
+ */
+@property (nonatomic, readonly) MGLStyle *style;
+
+/**
URLs of the styles bundled with the library.
@deprecated Call the relevant class method of `MGLStyle` for the URL of a
@@ -134,6 +149,9 @@ IB_DESIGNABLE
If you set this property to `nil`, the receiver will use the default style
and this property will automatically be set to that style’s URL.
+
+ If you want to modify the current style without replacing it outright, or if
+ you want to introspect individual style attributes, use the `style` property.
*/
@property (nonatomic, null_resettable) NSURL *styleURL;
@@ -590,7 +608,7 @@ IB_DESIGNABLE
@param animated Specify `YES` to animate the change by smoothly scrolling and
zooming or `NO` to immediately display the given bounds.
*/
-- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets animated:(BOOL)animated;
+- (void)setVisibleCoordinates:(const CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets animated:(BOOL)animated;
/**
Changes the receiver’s viewport to fit all of the given coordinates and
@@ -607,7 +625,7 @@ IB_DESIGNABLE
@param function The timing function to animate the change.
@param completion The block executed after the animation finishes.
*/
-- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion;
+- (void)setVisibleCoordinates:(const CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion;
/**
Sets the visible region so that the map displays the specified annotations.
@@ -1077,10 +1095,6 @@ IB_DESIGNABLE
*/
- (void)removeOverlays:(NS_ARRAY_OF(id <MGLOverlay>) *)overlays;
-#pragma mark - Runtime styling API
-
-- (MGLStyle *)style;
-
#pragma mark Accessing the Underlying Map Data
/**
@@ -1135,6 +1149,14 @@ IB_DESIGNABLE
To find out the layer names in a particular style, view the style in
<a href="https://www.mapbox.com/studio/">Mapbox Studio</a>.
+ @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 the
+ 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.
+
@param point A point expressed in the map view’s coordinate system.
@param styleLayerIdentifiers A set of strings that correspond to the names of
layers defined in the current style. Only the features contained in these
@@ -1198,6 +1220,14 @@ IB_DESIGNABLE
To find out the layer names in a particular style, view the style in
<a href="https://www.mapbox.com/studio/">Mapbox Studio</a>.
+ @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 the
+ 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.
+
@param rect A rectangle expressed in the map view’s coordinate system.
@param styleLayerIdentifiers A set of strings that correspond to the names of
layers defined in the current style. Only the features contained in these
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index bff17fa0ea..3c019d4726 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -236,6 +236,8 @@ public:
@property (nonatomic, readwrite) UIButton *attributionButton;
@property (nonatomic) NS_MUTABLE_ARRAY_OF(NSLayoutConstraint *) *attributionButtonConstraints;
@property (nonatomic) UIActionSheet *attributionSheet;
+@property (nonatomic, readwrite) MGLStyle *style;
+@property (nonatomic) UITapGestureRecognizer *singleTapGestureRecognizer;
@property (nonatomic) UIPanGestureRecognizer *pan;
@property (nonatomic) UIPinchGestureRecognizer *pinch;
@property (nonatomic) UIRotationGestureRecognizer *rotate;
@@ -284,6 +286,8 @@ public:
std::vector<MGLAnnotationTag> _annotationsNearbyLastTap;
CGPoint _initialImplicitCalloutViewOffset;
NSDate *_userLocationAnimationCompletionDate;
+ /// True if a willChange notification has been issued for shape annotation layers and a didChange notification is pending.
+ BOOL _isChangingAnnotationLayers;
BOOL _isWaitingForRedundantReachableNotification;
BOOL _isTargetingInterfaceBuilder;
@@ -355,14 +359,17 @@ public:
- (void)setStyleURL:(nullable NSURL *)styleURL
{
if (_isTargetingInterfaceBuilder) return;
-
+
if ( ! styleURL)
{
styleURL = [MGLStyle streetsStyleURLWithVersion:MGLStyleDefaultVersion];
}
styleURL = styleURL.mgl_URLByStandardizingScheme;
+ [self willChangeValueForKey:@"style"];
+ _style = [[MGLStyle alloc] initWithMapView:self];
_mbglMap->setStyleURL([[styleURL absoluteString] UTF8String]);
+ [self didChangeValueForKey:@"style"];
}
- (IBAction)reloadStyle:(__unused id)sender {
@@ -466,10 +473,8 @@ public:
_compassView.accessibilityTraits = UIAccessibilityTraitButton;
_compassView.accessibilityLabel = NSLocalizedStringWithDefaultValue(@"COMPASS_A11Y_LABEL", nil, nil, @"Compass", @"Accessibility label");
_compassView.accessibilityHint = NSLocalizedStringWithDefaultValue(@"COMPASS_A11Y_HINT", nil, nil, @"Rotates the map to face due north", @"Accessibility hint");
- UIView *container = [[UIView alloc] initWithFrame:CGRectZero];
- [container addSubview:_compassView];
- container.translatesAutoresizingMaskIntoConstraints = NO;
- [self addSubview:container];
+ _compassView.translatesAutoresizingMaskIntoConstraints = NO;
+ [self addSubview:_compassView];
_compassViewConstraints = [NSMutableArray array];
// setup interaction
@@ -494,9 +499,10 @@ public:
doubleTap.numberOfTapsRequired = 2;
[self addGestureRecognizer:doubleTap];
- UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)];
- [singleTap requireGestureRecognizerToFail:doubleTap];
- [self addGestureRecognizer:singleTap];
+ _singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTapGesture:)];
+ [_singleTapGestureRecognizer requireGestureRecognizerToFail:doubleTap];
+ _singleTapGestureRecognizer.delegate = self;
+ [self addGestureRecognizer:_singleTapGestureRecognizer];
UITapGestureRecognizer *twoFingerTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTwoFingerTapGesture:)];
twoFingerTap.numberOfTouchesRequired = 2;
@@ -531,6 +537,8 @@ public:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wakeGL:) name:UIApplicationWillEnterForegroundNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(wakeGL:) name:UIApplicationDidBecomeActiveNotification object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveMemoryWarning) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:UIDeviceOrientationDidChangeNotification object:nil];
+ [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
// set initial position
//
@@ -630,13 +638,6 @@ public:
return image;
}
-- (MGLStyle *)style
-{
- MGLStyle *style = [[MGLStyle alloc] init];
- style.mapView = self;
- return style;
-}
-
- (void)reachabilityChanged:(NSNotification *)notification
{
MGLReachability *reachability = [notification object];
@@ -649,6 +650,7 @@ public:
- (void)dealloc
{
+ [[UIDevice currentDevice] endGeneratingDeviceOrientationNotifications];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[_attributionButton removeObserver:self forKeyPath:@"hidden"];
@@ -770,23 +772,15 @@ public:
- (void)updateConstraints
{
- // If we have a view controller reference, use its layout guides for our various top & bottom
- // views so they don't underlap navigation or tool bars. If we don't have a reference, apply
- // constraints against ourself to maintain (albeit less ideal) placement of the subviews.
- //
- UIViewController *viewController = self.viewControllerForLayoutGuides;
- UIView *constraintParentView = (viewController.view ? viewController.view : self);
-
// compass
//
- UIView *compassContainer = self.compassView.superview;
- [constraintParentView removeConstraints:self.compassViewConstraints];
+ [self removeConstraints:self.compassViewConstraints];
[self.compassViewConstraints removeAllObjects];
[self.compassViewConstraints addObject:
- [NSLayoutConstraint constraintWithItem:compassContainer
+ [NSLayoutConstraint constraintWithItem:self.compassView
attribute:NSLayoutAttributeTop
- relatedBy:NSLayoutRelationGreaterThanOrEqual
+ relatedBy:NSLayoutRelationEqual
toItem:self
attribute:NSLayoutAttributeTop
multiplier:1
@@ -796,40 +790,22 @@ public:
[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
- toItem:compassContainer
+ toItem:self.compassView
attribute:NSLayoutAttributeTrailing
multiplier:1
constant:5 + self.contentInset.right]];
- UIImage *compassImage = self.compassView.image;
- [self.compassViewConstraints addObject:
- [NSLayoutConstraint constraintWithItem:compassContainer
- attribute:NSLayoutAttributeWidth
- relatedBy:NSLayoutRelationEqual
- toItem:nil
- attribute:NSLayoutAttributeNotAnAttribute
- multiplier:1
- constant:compassImage.size.width]];
-
- [self.compassViewConstraints addObject:
- [NSLayoutConstraint constraintWithItem:compassContainer
- attribute:NSLayoutAttributeHeight
- relatedBy:NSLayoutRelationEqual
- toItem:nil
- attribute:NSLayoutAttributeNotAnAttribute
- multiplier:1
- constant:compassImage.size.height]];
- [constraintParentView addConstraints:self.compassViewConstraints];
+ [self addConstraints:self.compassViewConstraints];
// logo bug
//
- [constraintParentView removeConstraints:self.logoViewConstraints];
+ [self removeConstraints:self.logoViewConstraints];
[self.logoViewConstraints removeAllObjects];
[self.logoViewConstraints addObject:
[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeBottom
- relatedBy:NSLayoutRelationGreaterThanOrEqual
+ relatedBy:NSLayoutRelationEqual
toItem:self.logoView
attribute:NSLayoutAttributeBaseline
multiplier:1
@@ -843,17 +819,17 @@ public:
attribute:NSLayoutAttributeLeading
multiplier:1
constant:8 + self.contentInset.left]];
- [constraintParentView addConstraints:self.logoViewConstraints];
+ [self addConstraints:self.logoViewConstraints];
// attribution button
//
- [constraintParentView removeConstraints:self.attributionButtonConstraints];
+ [self removeConstraints:self.attributionButtonConstraints];
[self.attributionButtonConstraints removeAllObjects];
[self.attributionButtonConstraints addObject:
[NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeBottom
- relatedBy:NSLayoutRelationGreaterThanOrEqual
+ relatedBy:NSLayoutRelationEqual
toItem:self.attributionButton
attribute:NSLayoutAttributeBaseline
multiplier:1
@@ -867,7 +843,7 @@ public:
attribute:NSLayoutAttributeTrailing
multiplier:1
constant:8 + self.contentInset.right]];
- [constraintParentView addConstraints:self.attributionButtonConstraints];
+ [self addConstraints:self.attributionButtonConstraints];
[super updateConstraints];
}
@@ -1072,6 +1048,11 @@ public:
[super didMoveToSuperview];
}
+- (void)deviceOrientationDidChange:(__unused NSNotification *)notification
+{
+ [self setNeedsLayout];
+}
+
- (void)sleepGL:(__unused NSNotification *)notification
{
MGLAssertIsMainThread();
@@ -1425,6 +1406,27 @@ public:
return;
}
+ id<MGLAnnotation>annotation = [self annotationForGestureRecognizer:singleTap persistingResults:YES];
+ if(annotation)
+ {
+ [self selectAnnotation:annotation animated:YES];
+ }
+ else
+ {
+ [self deselectAnnotation:self.selectedAnnotation animated:YES];
+ }
+}
+
+/**
+ Returns the annotation that would be selected by a tap gesture recognizer.
+
+ This is used when a gesture is recognized, and to check if the gesture should be recognized.
+
+ @param singleTap An in progress tap gesture recognizer.
+ @param persist True to remember the cycleable set of annotations. @see annotationTagAtPoint:persistingResults
+ */
+- (nullable id <MGLAnnotation>)annotationForGestureRecognizer:(UITapGestureRecognizer*)singleTap persistingResults:(BOOL)persist
+{
CGPoint tapPoint = [singleTap locationInView:self];
if (self.userLocationVisible)
@@ -1439,19 +1441,19 @@ public:
// Get the tap point within the custom hit test layer.
tapPointForUserLocation = [singleTap locationInView:self.userLocationAnnotationView];
}
-
+
CALayer *hitLayer = [self.userLocationAnnotationView.hitTestLayer hitTest:tapPointForUserLocation];
-
+
if (hitLayer)
{
if ( ! _userLocationAnnotationIsSelected)
{
- [self selectAnnotation:self.userLocation animated:YES];
+ return self.userLocation;
}
- return;
+ return nil;
}
}
-
+
// Handle the case of an offset annotation view by converting the tap point to be the geo location
// of the annotation itself that the view represents
for (MGLAnnotationView *view in self.annotationContainerView.annotationViews)
@@ -1463,21 +1465,19 @@ public:
}
}
}
-
- MGLAnnotationTag hitAnnotationTag = [self annotationTagAtPoint:tapPoint persistingResults:YES];
+
+ MGLAnnotationTag hitAnnotationTag = [self annotationTagAtPoint:tapPoint persistingResults:persist];
if (hitAnnotationTag != MGLAnnotationTagNotFound)
{
if (hitAnnotationTag != _selectedAnnotationTag)
{
id <MGLAnnotation> annotation = [self annotationWithTag:hitAnnotationTag];
NSAssert(annotation, @"Cannot select nonexistent annotation with tag %u", hitAnnotationTag);
- [self selectAnnotation:annotation animated:YES];
+ return annotation;
}
}
- else
- {
- [self deselectAnnotation:self.selectedAnnotation animated:YES];
- }
+
+ return nil;
}
- (void)handleDoubleTapGesture:(UITapGestureRecognizer *)doubleTap
@@ -1635,6 +1635,17 @@ public:
}
}
}
+ else if (gestureRecognizer == _singleTapGestureRecognizer)
+ {
+ //Gesture will be recognized if it could deselect an annotation
+ if(!self.selectedAnnotation)
+ {
+ id<MGLAnnotation>annotation = [self annotationForGestureRecognizer:(UITapGestureRecognizer*)gestureRecognizer persistingResults:NO];
+ if(!annotation) {
+ return NO;
+ }
+ }
+ }
return YES;
}
@@ -2379,27 +2390,27 @@ public:
animated:animated];
}
-- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets animated:(BOOL)animated
+- (void)setVisibleCoordinates:(const CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets animated:(BOOL)animated
{
[self setVisibleCoordinates:coordinates count:count edgePadding:insets direction:self.direction animated:animated];
}
-- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction animated:(BOOL)animated
+- (void)setVisibleCoordinates:(const CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction animated:(BOOL)animated
{
[self setVisibleCoordinates:coordinates count:count edgePadding:insets direction:direction duration:animated ? MGLAnimationDuration : 0 animationTimingFunction:nil];
}
-- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function {
+- (void)setVisibleCoordinates:(const CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function {
[self setVisibleCoordinates:coordinates count:count edgePadding:insets direction:direction duration:duration animationTimingFunction:function completionHandler:NULL];
}
-- (void)setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion
+- (void)setVisibleCoordinates:(const CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion
{
self.userTrackingMode = MGLUserTrackingModeNone;
[self _setVisibleCoordinates:coordinates count:count edgePadding:insets direction:direction duration:duration animationTimingFunction:function completionHandler:completion];
}
-- (void)_setVisibleCoordinates:(CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion
+- (void)_setVisibleCoordinates:(const CLLocationCoordinate2D *)coordinates count:(NSUInteger)count edgePadding:(UIEdgeInsets)insets direction:(CLLocationDirection)direction duration:(NSTimeInterval)duration animationTimingFunction:(nullable CAMediaTimingFunction *)function completionHandler:(nullable void (^)(void))completion
{
_mbglMap->cancelTransitions();
@@ -2844,7 +2855,11 @@ public:
for (auto const& annotationTag: annotationTags)
{
- MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag[annotationTag];
+ if (!_annotationContextsByAnnotationTag.count(annotationTag))
+ {
+ continue;
+ }
+ MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
[annotations addObject:annotationContext.annotation];
}
@@ -2869,19 +2884,13 @@ public:
/// Returns the annotation tag assigned to the given annotation. Relatively expensive.
- (MGLAnnotationTag)annotationTagForAnnotation:(id <MGLAnnotation>)annotation
{
- if ( ! annotation || annotation == self.userLocation)
+ if ( ! annotation || annotation == self.userLocation
+ || _annotationTagsByAnnotation.count(annotation) == 0)
{
return MGLAnnotationTagNotFound;
}
-
- for (auto &pair : _annotationContextsByAnnotationTag)
- {
- if (pair.second.annotation == annotation)
- {
- return pair.first;
- }
- }
- return MGLAnnotationTagNotFound;
+
+ return _annotationTagsByAnnotation.at(annotation);
}
- (void)addAnnotation:(id <MGLAnnotation>)annotation
@@ -2911,6 +2920,12 @@ public:
{
NSAssert([annotation conformsToProtocol:@protocol(MGLAnnotation)], @"annotation should conform to MGLAnnotation");
+ // adding the same annotation object twice is a no-op
+ if ([self.annotations containsObject:annotation])
+ {
+ continue;
+ }
+
if ([annotation isKindOfClass:[MGLMultiPoint class]])
{
// The polyline or polygon knows how to style itself (with the map view’s help).
@@ -2919,10 +2934,12 @@ public:
continue;
}
+ _isChangingAnnotationLayers = YES;
MGLAnnotationTag annotationTag = _mbglMap->addAnnotation([multiPoint annotationObjectWithDelegate:self]);
MGLAnnotationContext context;
context.annotation = annotation;
_annotationContextsByAnnotationTag[annotationTag] = context;
+ _annotationTagsByAnnotation[annotation] = annotationTag;
[(NSObject *)annotation addObserver:self forKeyPath:@"coordinates" options:0 context:(void *)(NSUInteger)annotationTag];
}
@@ -3014,6 +3031,10 @@ public:
[self updateAnnotationContainerViewWithAnnotationViews:newAnnotationViews];
[self didChangeValueForKey:@"annotations"];
+ if (_isChangingAnnotationLayers)
+ {
+ [self.style willChangeValueForKey:@"layers"];
+ }
if ([self.delegate respondsToSelector:@selector(mapView:didAddAnnotationViews:)])
{
@@ -3098,7 +3119,14 @@ public:
- (nullable MGLAnnotationView *)viewForAnnotation:(id<MGLAnnotation>)annotation
{
- MGLAnnotationTag annotationTag = _annotationTagsByAnnotation.at(annotation);
+ if (annotation == self.userLocation)
+ {
+ return self.userLocationAnnotationView;
+ }
+ MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation];
+ if (annotationTag == MGLAnnotationTagNotFound) {
+ return nil;
+ }
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
return annotationContext.annotationView;
}
@@ -3229,11 +3257,16 @@ public:
[(NSObject *)annotation removeObserver:self forKeyPath:@"coordinates" context:(void *)(NSUInteger)annotationTag];
}
+ _isChangingAnnotationLayers = YES;
_mbglMap->removeAnnotation(annotationTag);
}
[self didChangeValueForKey:@"annotations"];
UIAccessibilityPostNotification(UIAccessibilityLayoutChangedNotification, nil);
+ if (_isChangingAnnotationLayers)
+ {
+ [self.style willChangeValueForKey:@"layers"];
+ }
}
- (void)addOverlay:(id <MGLOverlay>)overlay
@@ -4575,6 +4608,10 @@ public:
}
case mbgl::MapChangeDidFinishLoadingMap:
{
+ [self.style willChangeValueForKey:@"sources"];
+ [self.style didChangeValueForKey:@"sources"];
+ [self.style willChangeValueForKey:@"layers"];
+ [self.style didChangeValueForKey:@"layers"];
if ([self.delegate respondsToSelector:@selector(mapViewDidFinishLoadingMap:)])
{
[self.delegate mapViewDidFinishLoadingMap:self];
@@ -4618,6 +4655,11 @@ public:
case mbgl::MapChangeDidFinishRenderingFrame:
case mbgl::MapChangeDidFinishRenderingFrameFullyRendered:
{
+ if (_isChangingAnnotationLayers)
+ {
+ _isChangingAnnotationLayers = NO;
+ [self.style didChangeValueForKey:@"layers"];
+ }
[self updateAnnotationViews];
if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingFrame:fullyRendered:)])
{
@@ -4627,6 +4669,11 @@ public:
}
case mbgl::MapChangeDidFinishLoadingStyle:
{
+ [self.style willChangeValueForKey:@"name"];
+ [self.style willChangeValueForKey:@"sources"];
+ [self.style didChangeValueForKey:@"sources"];
+ [self.style willChangeValueForKey:@"layers"];
+ [self.style didChangeValueForKey:@"layers"];
if ([self.delegate respondsToSelector:@selector(mapView:didFinishLoadingStyle:)])
{
[self.delegate mapView:self didFinishLoadingStyle:self.style];
@@ -4672,9 +4719,9 @@ public:
continue;
}
- // Get the annotation tag then use it to get the context. This avoids the expensive lookup
- // by tag in `annotationTagForAnnotation:`
- MGLAnnotationTag annotationTag = _annotationTagsByAnnotation.at(annotation);
+ // Get the annotation tag then use it to get the context.
+ MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation];
+ NSAssert(annotationTag != MGLAnnotationTagNotFound, @"-visibleAnnotationsInRect: returned unrecognized annotation");
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
MGLAnnotationView *annotationView = annotationContext.annotationView;
@@ -4712,13 +4759,20 @@ public:
// Enqueue (and move if required) offscreen annotation views
for (id<MGLAnnotation> annotation in offscreenAnnotations)
{
- CLLocationCoordinate2D coordinate = annotation.coordinate;
- MGLAnnotationTag annotationTag = _annotationTagsByAnnotation.at(annotation);
+ // Defer to the shape/polygon styling delegate methods
+ if ([annotation isKindOfClass:[MGLMultiPoint class]])
+ {
+ continue;
+ }
+
+ MGLAnnotationTag annotationTag = [self annotationTagForAnnotation:annotation];
+ NSAssert(annotationTag != MGLAnnotationTagNotFound, @"-visibleAnnotationsInRect: returned unrecognized annotation");
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
UIView *annotationView = annotationContext.annotationView;
if (annotationView)
{
+ CLLocationCoordinate2D coordinate = annotation.coordinate;
// Every so often (1 out of 1000 frames?) the mbgl query mechanism fails. This logic spot checks the
// offscreenAnnotations values -- if they are actually still on screen then the view center is
// moved and the enqueue operation is avoided. This allows us to keep the performance benefit of
@@ -5076,16 +5130,28 @@ public:
void activate() override
{
+ if (activationCount++)
+ {
+ return;
+ }
+
[EAGLContext setCurrentContext:nativeView.context];
}
void deactivate() override
{
+ if (--activationCount)
+ {
+ return;
+ }
+
[EAGLContext setCurrentContext:nil];
}
private:
__weak MGLMapView *nativeView = nullptr;
+
+ NSUInteger activationCount = 0;
};
@end
diff --git a/platform/ios/src/MGLMapboxEvents.m b/platform/ios/src/MGLMapboxEvents.m
index e26ca51f8e..01c46b5c8b 100644
--- a/platform/ios/src/MGLMapboxEvents.m
+++ b/platform/ios/src/MGLMapboxEvents.m
@@ -35,6 +35,7 @@ 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";
@@ -46,7 +47,6 @@ static NSString *const MGLEventKeyOperatingSystem = @"operatingSystem";
static NSString *const MGLEventKeyResolution = @"resolution";
static NSString *const MGLEventKeyAccessibilityFontScale = @"accessibilityFontScale";
static NSString *const MGLEventKeyOrientation = @"orientation";
-static NSString *const MGLEventKeyBatteryLevel = @"batteryLevel";
static NSString *const MGLEventKeyPluggedIn = @"pluggedIn";
static NSString *const MGLEventKeyWifi = @"wifi";
static NSString *const MGLEventKeySource = @"source";
@@ -190,9 +190,6 @@ const NSTimeInterval MGLFlushInterval = 180;
// Clear Any System TimeZone Cache
[NSTimeZone resetSystemTimeZone];
[_rfc3339DateFormatter setTimeZone:[NSTimeZone systemTimeZone]];
-
- // Enable Battery Monitoring
- [UIDevice currentDevice].batteryMonitoringEnabled = YES;
// Configure logging
if ([self isProbablyAppStoreBuild]) {
@@ -454,7 +451,6 @@ const NSTimeInterval MGLFlushInterval = 180;
MGLEventKeyResolution: @(self.data.scale),
MGLEventKeyAccessibilityFontScale: @([self contentSizeScale]),
MGLEventKeyOrientation: [self deviceOrientation],
- MGLEventKeyBatteryLevel: @([self batteryLevel]),
MGLEventKeyWifi: @([[MGLReachability reachabilityForLocalWiFi] isReachableViaWiFi])} mutableCopy];
[self addBatteryStateToAttributes:attributes];
return [self eventForAttributes:attributes attributeDictionary:attributeDictionary];
@@ -475,7 +471,6 @@ const NSTimeInterval MGLFlushInterval = 180;
- (MGLMutableMapboxEventAttributes *)interactionEvent {
MGLMutableMapboxEventAttributes *attributes = [@{MGLEventKeyCreated: [self.rfc3339DateFormatter stringFromDate:[NSDate date]],
MGLEventKeyOrientation: [self deviceOrientation],
- MGLEventKeyBatteryLevel: @([self batteryLevel]),
MGLEventKeyWifi: @([[MGLReachability reachabilityForLocalWiFi] isReachableViaWiFi])} mutableCopy];
[self addBatteryStateToAttributes:attributes];
return attributes;
@@ -519,10 +514,6 @@ const NSTimeInterval MGLFlushInterval = 180;
repeats:YES];
}
-- (NSInteger)batteryLevel {
- return [[NSNumber numberWithFloat:roundf(100 * [UIDevice currentDevice].batteryLevel)] integerValue];
-}
-
- (NSString *)deviceOrientation {
NSString *result;
@@ -669,7 +660,8 @@ const NSTimeInterval MGLFlushInterval = 180;
[MGLMapboxEvents pushEvent:MGLEventTypeLocation withAttributes:@{MGLEventKeyCreated: formattedDate,
MGLEventKeyLatitude: @(lat),
MGLEventKeyLongitude: @(lng),
- MGLEventKeyAltitude: @(round(loc.altitude))}];
+ MGLEventKeyAltitude: @(round(loc.altitude)),
+ MGLEventHorizontalAccuracy: @(loc.horizontalAccuracy)}];
}
}
diff --git a/platform/ios/src/Mapbox.h b/platform/ios/src/Mapbox.h
index c2fda1be1f..7664695315 100644
--- a/platform/ios/src/Mapbox.h
+++ b/platform/ios/src/Mapbox.h
@@ -51,5 +51,6 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[];
#import "MGLUserLocation.h"
#import "MGLUserLocationAnnotationView.h"
#import "NSValue+MGLAdditions.h"
+#import "NSValue+MGLStyleEnumAttributeAdditions.h"
#import "MGLStyleValue.h"
#import "MGLTileSet.h"
diff --git a/platform/ios/uitest/ios-tests.xcodeproj/project.pbxproj b/platform/ios/uitest/ios-tests.xcodeproj/project.pbxproj
index 0d6f89234d..c9744d41bf 100644
--- a/platform/ios/uitest/ios-tests.xcodeproj/project.pbxproj
+++ b/platform/ios/uitest/ios-tests.xcodeproj/project.pbxproj
@@ -9,6 +9,7 @@
/* Begin PBXBuildFile section */
96567A231B0E84CD00D78776 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 96567A221B0E84CD00D78776 /* LaunchScreen.xib */; };
96567A311B0E8BB900D78776 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 96567A301B0E8BB900D78776 /* Images.xcassets */; };
+ DA180EF21DD1A4DF000A211D /* OHHTTPStubs.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA180EF11DD1A4DF000A211D /* OHHTTPStubs.framework */; };
DA482C801C12582600772FE3 /* Mapbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DA482C7F1C12582600772FE3 /* Mapbox.framework */; };
DA482C811C12582600772FE3 /* Mapbox.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = DA482C7F1C12582600772FE3 /* Mapbox.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
DA9C551D1CD9DFCD000A15C6 /* libKIF.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DA9C551B1CD9DFA7000A15C6 /* libKIF.a */; };
@@ -17,12 +18,6 @@
DD043366196DBBE000E6F39D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = DD043365196DBBE000E6F39D /* main.m */; };
DD0580E81ACB628200B112C9 /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DD0580E71ACB628200B112C9 /* IOKit.framework */; };
DD0E6F841B0190E200DC035A /* libOCMock.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DD0E6F701B0190E200DC035A /* libOCMock.a */; };
- DD0E6F981B01B68E00DC035A /* OHHTTPStubs.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0E6F8E1B01B68E00DC035A /* OHHTTPStubs.m */; };
- DD0E6F991B01B68E00DC035A /* OHHTTPStubs+NSURLSessionConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0E6F8F1B01B68E00DC035A /* OHHTTPStubs+NSURLSessionConfiguration.m */; };
- DD0E6F9A1B01B68E00DC035A /* OHHTTPStubsResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0E6F911B01B68E00DC035A /* OHHTTPStubsResponse.m */; };
- DD0E6F9B1B01B68E00DC035A /* OHHTTPStubsResponse+HTTPMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0E6F931B01B68E00DC035A /* OHHTTPStubsResponse+HTTPMessage.m */; };
- DD0E6F9C1B01B68E00DC035A /* OHHTTPStubsResponse+JSON.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0E6F951B01B68E00DC035A /* OHHTTPStubsResponse+JSON.m */; };
- DD0E6F9D1B01B68E00DC035A /* OHPathHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = DD0E6F971B01B68E00DC035A /* OHPathHelpers.m */; };
DDBD016C196DC4740033959E /* MapViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DDBD0168196DC4740033959E /* MapViewTests.m */; };
DDBD016D196DC4740033959E /* KIFTestActor+MapboxGL.m in Sources */ = {isa = PBXBuildFile; fileRef = DDBD016A196DC4740033959E /* KIFTestActor+MapboxGL.m */; };
/* End PBXBuildFile section */
@@ -54,9 +49,9 @@
/* Begin PBXFileReference section */
96567A221B0E84CD00D78776 /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = SOURCE_ROOT; };
96567A301B0E8BB900D78776 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = SOURCE_ROOT; };
+ DA180EF11DD1A4DF000A211D /* OHHTTPStubs.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OHHTTPStubs.framework; path = "OHHTTPStubs/OHHTTPStubs/build/Debug-iphoneos/OHHTTPStubs.framework"; sourceTree = "<group>"; };
DA482C7F1C12582600772FE3 /* Mapbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Mapbox.framework; sourceTree = BUILT_PRODUCTS_DIR; };
DA9C551B1CD9DFA7000A15C6 /* libKIF.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libKIF.a; path = "../../../build/ios/Build/Products/Debug-iphonesimulator/libKIF.a"; sourceTree = "<group>"; };
- DADD9EB51BD16D8B00DA9161 /* Compatibility.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Compatibility.h; path = OHHTTPStubs/OHHTTPStubs/Sources/Compatibility.h; sourceTree = SOURCE_ROOT; };
DD043323196DB9BC00E6F39D /* Mapbox GL Tests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Mapbox GL Tests.app"; sourceTree = BUILT_PRODUCTS_DIR; };
DD04335F196DBBD500E6F39D /* MGLTAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLTAppDelegate.m; sourceTree = SOURCE_ROOT; };
DD043360196DBBD500E6F39D /* MGLTViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLTViewController.m; sourceTree = SOURCE_ROOT; };
@@ -75,17 +70,6 @@
DD0E6F781B0190E200DC035A /* OCMockObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMockObject.h; sourceTree = "<group>"; };
DD0E6F791B0190E200DC035A /* OCMRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMRecorder.h; sourceTree = "<group>"; };
DD0E6F7A1B0190E200DC035A /* OCMStubRecorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OCMStubRecorder.h; sourceTree = "<group>"; };
- DD0E6F8D1B01B68E00DC035A /* OHHTTPStubs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OHHTTPStubs.h; path = OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.h; sourceTree = SOURCE_ROOT; };
- DD0E6F8E1B01B68E00DC035A /* OHHTTPStubs.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OHHTTPStubs.m; path = OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs.m; sourceTree = SOURCE_ROOT; };
- DD0E6F8F1B01B68E00DC035A /* OHHTTPStubs+NSURLSessionConfiguration.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "OHHTTPStubs+NSURLSessionConfiguration.m"; path = "OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubs+NSURLSessionConfiguration.m"; sourceTree = SOURCE_ROOT; };
- DD0E6F901B01B68E00DC035A /* OHHTTPStubsResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OHHTTPStubsResponse.h; path = OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.h; sourceTree = SOURCE_ROOT; };
- DD0E6F911B01B68E00DC035A /* OHHTTPStubsResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OHHTTPStubsResponse.m; path = OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse.m; sourceTree = SOURCE_ROOT; };
- DD0E6F921B01B68E00DC035A /* OHHTTPStubsResponse+HTTPMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "OHHTTPStubsResponse+HTTPMessage.h"; path = "OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+HTTPMessage.h"; sourceTree = SOURCE_ROOT; };
- DD0E6F931B01B68E00DC035A /* OHHTTPStubsResponse+HTTPMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "OHHTTPStubsResponse+HTTPMessage.m"; path = "OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+HTTPMessage.m"; sourceTree = SOURCE_ROOT; };
- DD0E6F941B01B68E00DC035A /* OHHTTPStubsResponse+JSON.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "OHHTTPStubsResponse+JSON.h"; path = "OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+JSON.h"; sourceTree = SOURCE_ROOT; };
- DD0E6F951B01B68E00DC035A /* OHHTTPStubsResponse+JSON.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "OHHTTPStubsResponse+JSON.m"; path = "OHHTTPStubs/OHHTTPStubs/Sources/OHHTTPStubsResponse+JSON.m"; sourceTree = SOURCE_ROOT; };
- DD0E6F961B01B68E00DC035A /* OHPathHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OHPathHelpers.h; path = OHHTTPStubs/OHHTTPStubs/Sources/OHPathHelpers.h; sourceTree = SOURCE_ROOT; };
- DD0E6F971B01B68E00DC035A /* OHPathHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OHPathHelpers.m; path = OHHTTPStubs/OHHTTPStubs/Sources/OHPathHelpers.m; sourceTree = SOURCE_ROOT; };
DDBD0152196DC3D70033959E /* Test Bundle.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Test Bundle.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
DDBD0165196DC4560033959E /* Bundle-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "Bundle-Info.plist"; sourceTree = SOURCE_ROOT; };
DDBD0168196DC4740033959E /* MapViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MapViewTests.m; sourceTree = SOURCE_ROOT; };
@@ -106,6 +90,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
+ DA180EF21DD1A4DF000A211D /* OHHTTPStubs.framework in Frameworks */,
DD0580E81ACB628200B112C9 /* IOKit.framework in Frameworks */,
DA9C551D1CD9DFCD000A15C6 /* libKIF.a in Frameworks */,
DD0E6F841B0190E200DC035A /* libOCMock.a in Frameworks */,
@@ -137,6 +122,7 @@
DD043325196DB9BC00E6F39D /* Frameworks */ = {
isa = PBXGroup;
children = (
+ DA180EF11DD1A4DF000A211D /* OHHTTPStubs.framework */,
DA9C551B1CD9DFA7000A15C6 /* libKIF.a */,
DA482C7F1C12582600772FE3 /* Mapbox.framework */,
DD0580E71ACB628200B112C9 /* IOKit.framework */,
@@ -194,25 +180,6 @@
path = OCMock/OCMock;
sourceTree = SOURCE_ROOT;
};
- DD0E6F861B01B67100DC035A /* OHHTTPStubs */ = {
- isa = PBXGroup;
- children = (
- DADD9EB51BD16D8B00DA9161 /* Compatibility.h */,
- DD0E6F8D1B01B68E00DC035A /* OHHTTPStubs.h */,
- DD0E6F8E1B01B68E00DC035A /* OHHTTPStubs.m */,
- DD0E6F8F1B01B68E00DC035A /* OHHTTPStubs+NSURLSessionConfiguration.m */,
- DD0E6F901B01B68E00DC035A /* OHHTTPStubsResponse.h */,
- DD0E6F911B01B68E00DC035A /* OHHTTPStubsResponse.m */,
- DD0E6F921B01B68E00DC035A /* OHHTTPStubsResponse+HTTPMessage.h */,
- DD0E6F931B01B68E00DC035A /* OHHTTPStubsResponse+HTTPMessage.m */,
- DD0E6F941B01B68E00DC035A /* OHHTTPStubsResponse+JSON.h */,
- DD0E6F951B01B68E00DC035A /* OHHTTPStubsResponse+JSON.m */,
- DD0E6F961B01B68E00DC035A /* OHPathHelpers.h */,
- DD0E6F971B01B68E00DC035A /* OHPathHelpers.m */,
- );
- name = OHHTTPStubs;
- sourceTree = "<group>";
- };
DDBD0139196DC38D0033959E /* Tests */ = {
isa = PBXGroup;
children = (
@@ -221,7 +188,6 @@
DDBD0168196DC4740033959E /* MapViewTests.m */,
DDBD0167196DC46B0033959E /* Supporting Files */,
DD0E6F6B1B01906600DC035A /* OCMock */,
- DD0E6F861B01B67100DC035A /* OHHTTPStubs */,
);
name = Tests;
path = "Mapbox GL Tests";
@@ -342,14 +308,8 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
- DD0E6F981B01B68E00DC035A /* OHHTTPStubs.m in Sources */,
- DD0E6F9C1B01B68E00DC035A /* OHHTTPStubsResponse+JSON.m in Sources */,
- DD0E6F9B1B01B68E00DC035A /* OHHTTPStubsResponse+HTTPMessage.m in Sources */,
DDBD016D196DC4740033959E /* KIFTestActor+MapboxGL.m in Sources */,
- DD0E6F991B01B68E00DC035A /* OHHTTPStubs+NSURLSessionConfiguration.m in Sources */,
- DD0E6F9A1B01B68E00DC035A /* OHHTTPStubsResponse.m in Sources */,
DDBD016C196DC4740033959E /* MapViewTests.m in Sources */,
- DD0E6F9D1B01B68E00DC035A /* OHPathHelpers.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -480,6 +440,10 @@
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Mapbox GL Tests.app/Mapbox GL Tests";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/OHHTTPStubs/OHHTTPStubs/build/Debug-iphoneos",
+ );
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
@@ -513,6 +477,10 @@
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Mapbox GL Tests.app/Mapbox GL Tests";
+ FRAMEWORK_SEARCH_PATHS = (
+ "$(inherited)",
+ "$(PROJECT_DIR)/OHHTTPStubs/OHHTTPStubs/build/Debug-iphoneos",
+ );
GCC_PREPROCESSOR_DEFINITIONS = "KIF_XCTEST=1";
HEADER_SEARCH_PATHS = (
"$(inherited)",
diff --git a/platform/macos/CHANGELOG.md b/platform/macos/CHANGELOG.md
index 8597665e46..2d377b813e 100644
--- a/platform/macos/CHANGELOG.md
+++ b/platform/macos/CHANGELOG.md
@@ -2,6 +2,10 @@
## master
+* Improved the line wrapping behavior of point-placed labels written in Chinese, Japanese, and Yi. ([#6828](https://github.com/mapbox/mapbox-gl-native/pull/6828))
+
+## 0.3.0
+
### Packaging
* Fixed an issue causing code signing failures and bloating the framework. ([#5850](https://github.com/mapbox/mapbox-gl-native/pull/5850))
@@ -17,7 +21,6 @@
* TileJSON manifests can now specify `"scheme": "tms"` to indicate the use of [TMS](https://en.wikipedia.org/wiki/Tile_Map_Service) coordinates. ([#2270](https://github.com/mapbox/mapbox-gl-native/pull/2270))
* Fixed an issue causing abstract `MGLMultiPointFeature` objects to be returned in feature query results. Now concrete `MGLPointCollectionFeature` objects are returned. ([#6742](https://github.com/mapbox/mapbox-gl-native/pull/6742))
* Fixed rendering artifacts and missing glyphs that occurred after viewing a large number of CJK characters on the map. ([#5908](https://github.com/mapbox/mapbox-gl-native/pull/5908))
-* Improved the line wrapping behavior of point-placed labels written in Chinese, Japanese, and Yi. ([#6828](https://github.com/mapbox/mapbox-gl-native/pull/6828))
* Fixed an issue where the style zoom levels were not respected when deciding when to render a layer. ([#5811](https://github.com/mapbox/mapbox-gl-native/issues/5811))
* Fixed an issue where feature querying sometimes failed to return the expected features when the map was tilted. ([#6773](https://github.com/mapbox/mapbox-gl-native/pull/6773))
* MGLFeature’s `attributes` and `identifier` properties are now writable. ([#6728](https://github.com/mapbox/mapbox-gl-native/pull/6728))
@@ -33,9 +36,10 @@
### Annotations
* Added `showAnnotations:animated:` and `showAnnotations:edgePadding:animated:`, which moves the map viewport to show the specified annotations. ([#5749](https://github.com/mapbox/mapbox-gl-native/pull/5749))
-* MGLPolyline annotations and the exterior coordinates of MGLPolygon annotations are now able to be mutated, part or all, and changes are displayed immediately. ([#6565](https://github.com/mapbox/mapbox-gl-native/pull/6565))
+* Added new methods to MGLMultiPoint for changing or appending vertices along polyline annotations and the exteriors of polygon annotations. ([#6565](https://github.com/mapbox/mapbox-gl-native/pull/6565))
* Added new APIs to MGLMapView to query for visible annotations. ([6061](https://github.com/mapbox/mapbox-gl-native/pull/6061))
* Deprecated `-[MGLMapViewDelegate mapView:alphaForShapeAnnotation:]` in favor of specifying an alpha component via `-[MGLMapViewDelegate mapView:strokeColorForShapeAnnotation:]` or `-[MGLMapViewDelegate mapView:fillColorForPolygonAnnotation:]`. ([#6706](https://github.com/mapbox/mapbox-gl-native/pull/6706))
+* Various method arguments that are represented as C arrays of `CLLocationCoordinate2D` instances have been marked `const` to streamline bridging to Swift. ([#7215](https://github.com/mapbox/mapbox-gl-native/pull/7215))
* To make an MGLPolyline or MGLPolygon span the antimeridian, specify coordinates with longitudes greater than 180° or less than −180°. ([#6088](https://github.com/mapbox/mapbox-gl-native/pull/6088))
* Fixed an issue where placing a point annotation on Null Island also placed a duplicate annotation on its antipode. ([#3563](https://github.com/mapbox/mapbox-gl-native/pull/3563))
* Improved the precision of annotations at zoom levels greater than 18. ([#5517](https://github.com/mapbox/mapbox-gl-native/pull/5517))
@@ -57,6 +61,7 @@
* Fixed an issue where the map view’s center would always be calculated as if the view occupied the entire window. ([#6102](https://github.com/mapbox/mapbox-gl-native/pull/6102))
* Notification names and user info keys are now string enumeration values for ease of use in Swift. ([#6794](https://github.com/mapbox/mapbox-gl-native/pull/6794))
* Fixed a typo in the documentation for the MGLCompassDirectionFormatter class. ([#5879](https://github.com/mapbox/mapbox-gl-native/pull/5879))
+* The NSClickGestureRecognizer on MGLMapView that is used for selecting annotations now fails if a click does not select an annotation. ([#7246](https://github.com/mapbox/mapbox-gl-native/pull/7246))
## 0.2.1 - July 19, 2016
diff --git a/platform/macos/DEVELOPING.md b/platform/macos/DEVELOPING.md
index cf52a650aa..71eb7995c8 100644
--- a/platform/macos/DEVELOPING.md
+++ b/platform/macos/DEVELOPING.md
@@ -86,6 +86,15 @@ To add or update text that the user may see in the macOS SDK:
1. _(Optional.)_ When dealing with a number followed by a pluralized word, do not split the string. Instead, use a format string and make `val` ambiguous, like `%d file(s)`. Then pluralize for English in the appropriate [.stringsdict file](https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html). See [platform/darwin/resources/en.lproj/Foundation.stringsdict](../darwin/resources/en.lproj/Foundation.stringsdict) for an example. Localizers should do likewise for their languages.
1. Run `make genstrings` and commit any changes it makes to .strings files. The make rule also updates the iOS SDK’s strings tables.
+### Adding a localization
+
+To add a localization to the macOS SDK:
+
+1. In macos.xcworkspace, open the project editor for macos.xcodeproj. Using the project editor’s sidebar or tab bar dropdown, go to the “macos” project; under the Localizations section of the Info tab, click the + button to add your language to the project.
+1. In the sheet that appears, select all the .strings and .stringsdict files but no .xib file. (Most of the XIBs are part of the macosapp example application, which is not localized, while MGLAnnotationCallout.xib contains no localizable strings.)
+1. In the Project navigator, expand each .strings and .stringsdict file in the project. An additional version for your localization should be listed; translate it. Translate everything on the right side of the equals sign. Leave the left side and any comments unmodified. See Apple’s documentation on the [.strings](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/LoadingResources/Strings/Strings.html) and [.stringsdict](https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPInternational/StringsdictFileFormat/StringsdictFileFormat.html) formats.
+1. You’re already most of the way towards localizing the iOS SDK too – consider [completing that localization](../ios/DEVELOPING.md#adding-a-localization).
+
## Access tokens
The demo applications use Mapbox vector tiles, which require a Mapbox account and API access token. Obtain an access token on the [Mapbox account page](https://www.mapbox.com/studio/account/tokens/). You will be prompted for this access token the first time you launch the demo application.
diff --git a/platform/macos/app/Assets.xcassets/Layers/Contents.json b/platform/macos/app/Assets.xcassets/Layers/Contents.json
new file mode 100644
index 0000000000..da4a164c91
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/Contents.json
@@ -0,0 +1,6 @@
+{
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Layers/background.imageset/Contents.json b/platform/macos/app/Assets.xcassets/Layers/background.imageset/Contents.json
new file mode 100644
index 0000000000..3d2c878879
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/background.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "background.pdf"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Layers/background.imageset/background.pdf b/platform/macos/app/Assets.xcassets/Layers/background.imageset/background.pdf
new file mode 100644
index 0000000000..95a50c1446
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/background.imageset/background.pdf
@@ -0,0 +1,69 @@
+%PDF-1.5
+%
+3 0 obj
+<< /Length 4 0 R
+ /Filter /FlateDecode
+>>
+stream
+x}Mj@ u
+] *I Hf1x ܋E?Oն ChgՓT>R2}̃7e7=y!^Epp$aC QeQavJ$6r\+6"uTwtȂ܄Cpoz>(@ \Q@Xx^o6f58KP::ۨv:DmEQu/z\';*U 2.޻2Up!ν5D>!PVQNvkhK:WEt1^9du.!Y c:Ox>1`,iDi(1^mc3ʸ`#(vKWt/Ѝ"5I7ag+vܧX1sփ!?8
+endstream
+endobj
+4 0 obj
+ 424
+endobj
+2 0 obj
+<<
+ /ExtGState <<
+ /a0 << /CA 1 /ca 1 >>
+ >>
+>>
+endobj
+5 0 obj
+<< /Type /Page
+ /Parent 1 0 R
+ /MediaBox [ 0 0 12.8 12.8 ]
+ /Contents 3 0 R
+ /Group <<
+ /Type /Group
+ /S /Transparency
+ /I true
+ /CS /DeviceRGB
+ >>
+ /Resources 2 0 R
+>>
+endobj
+1 0 obj
+<< /Type /Pages
+ /Kids [ 5 0 R ]
+ /Count 1
+>>
+endobj
+6 0 obj
+<< /Creator (cairo 1.14.0 (http://cairographics.org))
+ /Producer (cairo 1.14.0 (http://cairographics.org))
+>>
+endobj
+7 0 obj
+<< /Type /Catalog
+ /Pages 1 0 R
+>>
+endobj
+xref
+0 8
+0000000000 65535 f
+0000000826 00000 n
+0000000538 00000 n
+0000000015 00000 n
+0000000516 00000 n
+0000000610 00000 n
+0000000891 00000 n
+0000001018 00000 n
+trailer
+<< /Size 8
+ /Root 7 0 R
+ /Info 6 0 R
+>>
+startxref
+1070
+%%EOF
diff --git a/platform/macos/app/Assets.xcassets/Layers/circle.imageset/Contents.json b/platform/macos/app/Assets.xcassets/Layers/circle.imageset/Contents.json
new file mode 100644
index 0000000000..c924214fd9
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/circle.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "circle.pdf"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Layers/circle.imageset/circle.pdf b/platform/macos/app/Assets.xcassets/Layers/circle.imageset/circle.pdf
new file mode 100644
index 0000000000..fde79a19bd
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/circle.imageset/circle.pdf
@@ -0,0 +1,70 @@
+%PDF-1.5
+%
+3 0 obj
+<< /Length 4 0 R
+ /Filter /FlateDecode
+>>
+stream
+x]M
+1 9Ż1?''aRAf1 X)GK ANv_4Nܩ š% 3Z
+cr'QJ2Wp{t\dImW 44J
+endstream
+endobj
+4 0 obj
+ 139
+endobj
+2 0 obj
+<<
+ /ExtGState <<
+ /a0 << /CA 1 /ca 1 >>
+ >>
+>>
+endobj
+5 0 obj
+<< /Type /Page
+ /Parent 1 0 R
+ /MediaBox [ 0 0 12.8 12.8 ]
+ /Contents 3 0 R
+ /Group <<
+ /Type /Group
+ /S /Transparency
+ /I true
+ /CS /DeviceRGB
+ >>
+ /Resources 2 0 R
+>>
+endobj
+1 0 obj
+<< /Type /Pages
+ /Kids [ 5 0 R ]
+ /Count 1
+>>
+endobj
+6 0 obj
+<< /Creator (cairo 1.14.0 (http://cairographics.org))
+ /Producer (cairo 1.14.0 (http://cairographics.org))
+>>
+endobj
+7 0 obj
+<< /Type /Catalog
+ /Pages 1 0 R
+>>
+endobj
+xref
+0 8
+0000000000 65535 f
+0000000541 00000 n
+0000000253 00000 n
+0000000015 00000 n
+0000000231 00000 n
+0000000325 00000 n
+0000000606 00000 n
+0000000733 00000 n
+trailer
+<< /Size 8
+ /Root 7 0 R
+ /Info 6 0 R
+>>
+startxref
+785
+%%EOF
diff --git a/platform/macos/app/Assets.xcassets/Layers/fill.imageset/Contents.json b/platform/macos/app/Assets.xcassets/Layers/fill.imageset/Contents.json
new file mode 100644
index 0000000000..ea68330e70
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/fill.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "fill.pdf"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Layers/fill.imageset/fill.pdf b/platform/macos/app/Assets.xcassets/Layers/fill.imageset/fill.pdf
new file mode 100644
index 0000000000..ca7e4cc505
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/fill.imageset/fill.pdf
Binary files differ
diff --git a/platform/macos/app/Assets.xcassets/Layers/symbol.imageset/Contents.json b/platform/macos/app/Assets.xcassets/Layers/symbol.imageset/Contents.json
new file mode 100644
index 0000000000..ad4293958f
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/symbol.imageset/Contents.json
@@ -0,0 +1,15 @@
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "symbol.pdf"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ },
+ "properties" : {
+ "template-rendering-intent" : "template"
+ }
+} \ No newline at end of file
diff --git a/platform/macos/app/Assets.xcassets/Layers/symbol.imageset/symbol.pdf b/platform/macos/app/Assets.xcassets/Layers/symbol.imageset/symbol.pdf
new file mode 100644
index 0000000000..ce4aaa198e
--- /dev/null
+++ b/platform/macos/app/Assets.xcassets/Layers/symbol.imageset/symbol.pdf
@@ -0,0 +1,71 @@
+%PDF-1.5
+%
+3 0 obj
+<< /Length 4 0 R
+ /Filter /FlateDecode
+>>
+stream
+x]A
+@ E9ſqIgR\EqqQ !'
+ua{ HXRLQ&~'/p#!ʎ26a0scR_CYr씪KFʖ9O׋.pN- yV
+yOh4
+endstream
+endobj
+4 0 obj
+ 152
+endobj
+2 0 obj
+<<
+ /ExtGState <<
+ /a0 << /CA 1 /ca 1 >>
+ >>
+>>
+endobj
+5 0 obj
+<< /Type /Page
+ /Parent 1 0 R
+ /MediaBox [ 0 0 12.8 12.8 ]
+ /Contents 3 0 R
+ /Group <<
+ /Type /Group
+ /S /Transparency
+ /I true
+ /CS /DeviceRGB
+ >>
+ /Resources 2 0 R
+>>
+endobj
+1 0 obj
+<< /Type /Pages
+ /Kids [ 5 0 R ]
+ /Count 1
+>>
+endobj
+6 0 obj
+<< /Creator (cairo 1.14.0 (http://cairographics.org))
+ /Producer (cairo 1.14.0 (http://cairographics.org))
+>>
+endobj
+7 0 obj
+<< /Type /Catalog
+ /Pages 1 0 R
+>>
+endobj
+xref
+0 8
+0000000000 65535 f
+0000000554 00000 n
+0000000266 00000 n
+0000000015 00000 n
+0000000244 00000 n
+0000000338 00000 n
+0000000619 00000 n
+0000000746 00000 n
+trailer
+<< /Size 8
+ /Root 7 0 R
+ /Info 6 0 R
+>>
+startxref
+798
+%%EOF
diff --git a/platform/macos/app/Base.lproj/MainMenu.xib b/platform/macos/app/Base.lproj/MainMenu.xib
index 716872a32a..cb9905d4a1 100644
--- a/platform/macos/app/Base.lproj/MainMenu.xib
+++ b/platform/macos/app/Base.lproj/MainMenu.xib
@@ -366,32 +366,32 @@
<items>
<menuItem title="Streets" state="on" tag="1" keyEquivalent="1" id="17N-yz-NNo">
<connections>
- <action selector="setStyle:" target="-1" id="I4L-Wx-UXA"/>
+ <action selector="showStyle:" target="-1" id="BGu-va-ftr"/>
</connections>
</menuItem>
<menuItem title="Outdoors" tag="2" keyEquivalent="2" id="BBa-Qa-SQr">
<connections>
- <action selector="setStyle:" target="-1" id="rM1-yG-t5u"/>
+ <action selector="showStyle:" target="-1" id="sQ3-b6-G1A"/>
</connections>
</menuItem>
<menuItem title="Light" tag="3" keyEquivalent="3" id="HWe-7u-UVJ">
<connections>
- <action selector="setStyle:" target="-1" id="Q9V-O1-oRz"/>
+ <action selector="showStyle:" target="-1" id="jMN-oR-sbZ"/>
</connections>
</menuItem>
<menuItem title="Dark" tag="4" keyEquivalent="4" id="6HI-q6-AeV">
<connections>
- <action selector="setStyle:" target="-1" id="YfH-1I-G50"/>
+ <action selector="showStyle:" target="-1" id="xgf-Sq-eJw"/>
</connections>
</menuItem>
<menuItem title="Satellite" tag="5" keyEquivalent="5" id="h0J-5X-kgF">
<connections>
- <action selector="setStyle:" target="-1" id="GXt-oK-Hy1"/>
+ <action selector="showStyle:" target="-1" id="YyE-2C-Vhj"/>
</connections>
</menuItem>
<menuItem title="Satellite Streets" tag="6" keyEquivalent="6" id="9BL-00-HFt">
<connections>
- <action selector="setStyle:" target="-1" id="oL4-AC-waq"/>
+ <action selector="showStyle:" target="-1" id="NTT-Y1-EqU"/>
</connections>
</menuItem>
<menuItem title="Custom Style…" id="L0h-86-2cU">
@@ -429,6 +429,32 @@
<action selector="toggleToolbarShown:" target="-1" id="BXY-wc-z0C"/>
</connections>
</menuItem>
+ <menuItem title="Show Layers" keyEquivalent="L" id="qtg-l9-BH3">
+ <connections>
+ <action selector="toggleLayers:" target="-1" id="YdA-Mr-MHi"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="8aO-Nm-fxF"/>
+ <menuItem title="Labels In" id="M7v-B1-vo3">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <menu key="submenu" title="Labels In" id="gOc-5u-4v5">
+ <items>
+ <menuItem title="Local Language" id="hTL-wF-DEs">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="setLabelLanguage:" target="-1" id="Zc4-TL-Cxe"/>
+ </connections>
+ </menuItem>
+ <menuItem title="Preferred Language" tag="1" id="PkP-Ne-ISX">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="setLabelLanguage:" target="-1" id="7Io-iF-xf8"/>
+ </connections>
+ </menuItem>
+ </items>
+ </menu>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="qTh-Hu-dGV"/>
</items>
</menu>
</menuItem>
diff --git a/platform/macos/app/Base.lproj/MapDocument.xib b/platform/macos/app/Base.lproj/MapDocument.xib
index 2fb02f9c47..e147ba83d0 100644
--- a/platform/macos/app/Base.lproj/MapDocument.xib
+++ b/platform/macos/app/Base.lproj/MapDocument.xib
@@ -1,40 +1,161 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11191" systemVersion="15G31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="15G1004" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
- <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11191"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11201"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="MapDocument">
<connections>
<outlet property="mapView" destination="q4d-kF-8Hi" id="7hI-dS-A5R"/>
<outlet property="mapViewContextMenu" destination="XbX-6a-Mgy" id="YD0-1r-5N2"/>
+ <outlet property="splitView" destination="IPR-fm-vk8" id="9xt-ar-uad"/>
+ <outlet property="styleLayersArrayController" destination="GXW-3J-Gff" id="Ygs-7o-juz"/>
+ <outlet property="styleLayersTableView" destination="Mm4-6F-qEb" id="TB5-ha-JJE"/>
<outlet property="window" destination="cSv-fg-MAQ" id="TBu-Mu-79N"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
+ <objectController objectClassName="MGLMapView" id="jxx-uM-ZTC" userLabel="Map View Object Controller">
+ <declaredKeys>
+ <string>style</string>
+ </declaredKeys>
+ <connections>
+ <outlet property="content" destination="q4d-kF-8Hi" id="Zpe-0y-eG3"/>
+ </connections>
+ </objectController>
+ <objectController objectClassName="MGLStyle" id="Xji-k6-iQ4" userLabel="Style Object Controller">
+ <declaredKeys>
+ <string>layers</string>
+ <string>name</string>
+ </declaredKeys>
+ <connections>
+ <binding destination="jxx-uM-ZTC" name="contentObject" keyPath="selection.style" id="60N-aU-tgJ"/>
+ </connections>
+ </objectController>
+ <arrayController objectClassName="MGLStyleLayer" avoidsEmptySelection="NO" id="GXW-3J-Gff" userLabel="Style Layers Array Controller">
+ <declaredKeys>
+ <string>identifier</string>
+ <string>visible</string>
+ </declaredKeys>
+ <connections>
+ <binding destination="Xji-k6-iQ4" name="contentArray" keyPath="selection.layers" id="X25-Nb-Brf"/>
+ </connections>
+ </arrayController>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" frameAutosaveName="MBXMapWindow" animationBehavior="default" id="cSv-fg-MAQ">
<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="512" height="480"/>
+ <rect key="contentRect" x="388" y="211" width="642" height="480"/>
<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="512" height="480"/>
+ <rect key="frame" x="0.0" y="0.0" width="642" height="480"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
- <customView translatesAutoresizingMaskIntoConstraints="NO" id="q4d-kF-8Hi" customClass="MGLMapView">
- <rect key="frame" x="0.0" y="0.0" width="512" height="480"/>
+ <splitView autosaveName="MBXLayersSplitView" dividerStyle="thin" vertical="YES" translatesAutoresizingMaskIntoConstraints="NO" id="IPR-fm-vk8">
+ <rect key="frame" x="0.0" y="0.0" width="642" height="480"/>
+ <subviews>
+ <scrollView borderType="none" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" usesPredominantAxisScrolling="NO" id="sMc-vT-RwH">
+ <rect key="frame" x="0.0" y="0.0" width="163" height="480"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <clipView key="contentView" id="bSc-hK-bzQ">
+ <rect key="frame" x="0.0" y="0.0" width="163" height="480"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <tableView verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnResizing="NO" autosaveColumns="NO" id="Mm4-6F-qEb">
+ <rect key="frame" x="0.0" y="0.0" width="163" height="480"/>
+ <autoresizingMask key="autoresizingMask"/>
+ <size key="intercellSpacing" width="3" height="2"/>
+ <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">
+ <tableHeaderCell key="headerCell" lineBreakMode="truncatingTail" borderStyle="border">
+ <font key="font" metaFont="smallSystem"/>
+ <color key="textColor" name="headerTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
+ </tableHeaderCell>
+ <imageCell key="dataCell" lineBreakMode="truncatingTail" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="symbol" id="JWq-c8-aB1"/>
+ <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
+ <connections>
+ <binding destination="GXW-3J-Gff" name="value" keyPath="arrangedObjects" id="ST5-mo-Mkt">
+ <dictionary key="options">
+ <bool key="NSConditionallySetsEnabled" value="NO"/>
+ <string key="NSValueTransformerName">StyleLayerIconTransformer</string>
+ </dictionary>
+ </binding>
+ </connections>
+ </tableColumn>
+ <tableColumn 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"/>
+ <color key="backgroundColor" name="headerColor" catalog="System" colorSpace="catalog"/>
+ </tableHeaderCell>
+ <textFieldCell key="dataCell" lineBreakMode="truncatingTail" selectable="YES" editable="YES" title="Text Cell" id="6wl-F2-yK2">
+ <font key="font" metaFont="system"/>
+ <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+ <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
+ </textFieldCell>
+ <tableColumnResizingMask key="resizingMask" resizeWithTable="YES" userResizable="YES"/>
+ <connections>
+ <binding destination="GXW-3J-Gff" name="value" keyPath="arrangedObjects.identifier" id="vQC-tc-CMF">
+ <dictionary key="options">
+ <bool key="NSConditionallySetsEditable" value="YES"/>
+ </dictionary>
+ </binding>
+ <binding destination="GXW-3J-Gff" name="fontItalic" keyPath="arrangedObjects.visible" id="6Wu-cz-WSI">
+ <dictionary key="options">
+ <string key="NSValueTransformerName">NSNegateBoolean</string>
+ </dictionary>
+ </binding>
+ </connections>
+ </tableColumn>
+ </tableColumns>
+ <connections>
+ <action trigger="doubleAction" selector="toggleStyleLayers:" target="-1" id="Q1v-2T-sIC"/>
+ <outlet property="menu" destination="OHX-Pa-tDw" id="wnL-Ux-WaH"/>
+ </connections>
+ </tableView>
+ </subviews>
+ </clipView>
+ <constraints>
+ <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="185" id="VQs-2Z-hmP"/>
+ </constraints>
+ <scroller key="horizontalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="YES" id="NDx-rn-TLj">
+ <rect key="frame" x="0.0" y="464" width="184.5" height="16"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </scroller>
+ <scroller key="verticalScroller" hidden="YES" verticalHuggingPriority="750" horizontal="NO" id="0vt-rI-sHB">
+ <rect key="frame" x="147" y="480" width="16" height="0.0"/>
+ <autoresizingMask key="autoresizingMask"/>
+ </scroller>
+ </scrollView>
+ <customView id="q4d-kF-8Hi" customClass="MGLMapView">
+ <rect key="frame" x="164" y="0.0" width="478" height="480"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <constraints>
+ <constraint firstAttribute="width" relation="greaterThanOrEqual" constant="200" id="kg3-4h-7Hl"/>
+ </constraints>
+ <connections>
+ <outlet property="delegate" destination="-2" id="dh2-0H-jFZ"/>
+ <outlet property="menu" destination="XbX-6a-Mgy" id="dSu-HR-Kq2"/>
+ </connections>
+ </customView>
+ </subviews>
+ <holdingPriorities>
+ <real value="250"/>
+ <real value="250"/>
+ </holdingPriorities>
<connections>
- <outlet property="delegate" destination="-2" id="dh2-0H-jFZ"/>
- <outlet property="menu" destination="XbX-6a-Mgy" id="dSu-HR-Kq2"/>
+ <outlet property="delegate" destination="-2" id="dbC-MC-CAy"/>
</connections>
- </customView>
+ </splitView>
</subviews>
<constraints>
- <constraint firstAttribute="bottom" secondItem="q4d-kF-8Hi" secondAttribute="bottom" id="L2t-Be-qWL"/>
- <constraint firstItem="q4d-kF-8Hi" firstAttribute="top" secondItem="TuG-C5-zLS" secondAttribute="top" id="T8A-o3-Bhq"/>
- <constraint firstItem="q4d-kF-8Hi" firstAttribute="leading" secondItem="TuG-C5-zLS" secondAttribute="leading" id="fGH-YW-Qd3"/>
- <constraint firstAttribute="trailing" secondItem="q4d-kF-8Hi" secondAttribute="trailing" id="yfG-iG-K4C"/>
+ <constraint firstAttribute="trailing" secondItem="IPR-fm-vk8" secondAttribute="trailing" id="ABk-5R-Uzg"/>
+ <constraint firstAttribute="bottom" secondItem="IPR-fm-vk8" secondAttribute="bottom" id="CHa-BK-6ld"/>
+ <constraint firstItem="IPR-fm-vk8" firstAttribute="leading" secondItem="TuG-C5-zLS" secondAttribute="leading" id="hcR-y2-x3l"/>
+ <constraint firstItem="IPR-fm-vk8" firstAttribute="top" secondItem="TuG-C5-zLS" secondAttribute="top" id="u78-BU-s5g"/>
</constraints>
</view>
<toolbar key="toolbar" implicitIdentifier="A3AC6577-4712-4628-813D-113498171A84" allowsUserCustomization="NO" displayMode="iconOnly" sizeMode="regular" id="DTc-AP-Bah">
@@ -86,11 +207,28 @@
</popUpButtonCell>
</popUpButton>
<connections>
- <action selector="setStyle:" target="-1" id="2Kw-9i-a3G"/>
+ <action selector="showStyle:" target="-1" id="pBn-SO-HIX"/>
+ </connections>
+ </toolbarItem>
+ <toolbarItem implicitItemIdentifier="ACA1D8BE-A108-4BF9-92DC-AE7AA7342CF9" label="Layers" paletteLabel="Show Layers" image="NSListViewTemplate" id="THR-Dm-mn8" customClass="ValidatedToolbarItem">
+ <nil key="toolTip"/>
+ <size key="minSize" width="47" height="32"/>
+ <size key="maxSize" width="48" height="32"/>
+ <button key="view" verticalHuggingPriority="750" id="C3e-Oy-STT">
+ <rect key="frame" x="14" y="14" width="47" height="32"/>
+ <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+ <buttonCell key="cell" type="roundTextured" bezelStyle="texturedRounded" image="NSListViewTemplate" imagePosition="only" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="2Gf-wm-QuI">
+ <behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES" changeBackground="YES" changeGray="YES"/>
+ <font key="font" metaFont="system"/>
+ </buttonCell>
+ </button>
+ <connections>
+ <action selector="toggleLayers:" target="-1" id="NHT-rn-BuG"/>
</connections>
</toolbarItem>
</allowedToolbarItems>
<defaultToolbarItems>
+ <toolbarItem reference="THR-Dm-mn8"/>
<toolbarItem reference="XJT-Ho-tuZ"/>
<toolbarItem reference="z4l-5x-MzK"/>
<toolbarItem reference="u23-0z-Otl"/>
@@ -135,8 +273,30 @@
</connections>
<point key="canvasLocation" x="820" y="254.5"/>
</menu>
+ <menu title="Layer" id="OHX-Pa-tDw" userLabel="Layers Context Menu">
+ <items>
+ <menuItem title="Show" id="KWq-LM-Qqo">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="toggleStyleLayers:" target="-1" id="kXn-ug-tWC"/>
+ </connections>
+ </menuItem>
+ <menuItem isSeparatorItem="YES" id="uWQ-uj-mZn"/>
+ <menuItem title="Delete" id="Myg-EZ-Pnq">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="deleteStyleLayers:" target="-1" id="cE5-ZP-BDC"/>
+ </connections>
+ </menuItem>
+ </items>
+ <connections>
+ <outlet property="delegate" destination="-2" id="yvb-NB-VGl"/>
+ </connections>
+ </menu>
</objects>
<resources>
+ <image name="NSListViewTemplate" width="14" height="10"/>
<image name="NSShareTemplate" width="11" height="16"/>
+ <image name="symbol" width="13" height="13"/>
</resources>
</document>
diff --git a/platform/macos/app/MapDocument.h b/platform/macos/app/MapDocument.h
index 86ad05e6e2..fa70212cf8 100644
--- a/platform/macos/app/MapDocument.h
+++ b/platform/macos/app/MapDocument.h
@@ -6,7 +6,7 @@
@property (weak) IBOutlet MGLMapView *mapView;
-- (IBAction)setStyle:(id)sender;
+- (IBAction)showStyle:(id)sender;
- (IBAction)chooseCustomStyle:(id)sender;
- (IBAction)reload:(id)sender;
diff --git a/platform/macos/app/MapDocument.m b/platform/macos/app/MapDocument.m
index e4fe202f3f..d2e6a0f810 100644
--- a/platform/macos/app/MapDocument.m
+++ b/platform/macos/app/MapDocument.m
@@ -46,9 +46,12 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
return flattenedShapes;
}
-@interface MapDocument () <NSWindowDelegate, NSSharingServicePickerDelegate, NSMenuDelegate, MGLMapViewDelegate>
+@interface MapDocument () <NSWindowDelegate, NSSharingServicePickerDelegate, NSMenuDelegate, NSSplitViewDelegate, MGLMapViewDelegate>
+@property (weak) IBOutlet NSArrayController *styleLayersArrayController;
+@property (weak) IBOutlet NSTableView *styleLayersTableView;
@property (weak) IBOutlet NSMenu *mapViewContextMenu;
+@property (weak) IBOutlet NSSplitView *splitView;
@end
@@ -61,6 +64,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
NSUInteger _droppedPinCounter;
NSNumberFormatter *_spellOutNumberFormatter;
+ BOOL _isLocalizingLabels;
BOOL _showsToolTipsOnDroppedPins;
BOOL _randomizesCursorsOnDroppedPins;
BOOL _isTouringWorld;
@@ -98,6 +102,8 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
NSPressGestureRecognizer *pressGestureRecognizer = [[NSPressGestureRecognizer alloc] initWithTarget:self action:@selector(handlePressGesture:)];
[self.mapView addGestureRecognizer:pressGestureRecognizer];
+ [self.splitView setPosition:0 ofDividerAtIndex:0];
+
[self applyPendingState];
}
@@ -118,10 +124,12 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
- (void)window:(NSWindow *)window willEncodeRestorableState:(NSCoder *)state {
[state encodeObject:self.mapView.styleURL forKey:@"MBXMapViewStyleURL"];
+ [state encodeBool:_isLocalizingLabels forKey:@"MBXLocalizeLabels"];
}
- (void)window:(NSWindow *)window didDecodeRestorableState:(NSCoder *)state {
self.mapView.styleURL = [state decodeObjectForKey:@"MBXMapViewStyleURL"];
+ _isLocalizingLabels = [state decodeBoolForKey:@"MBXLocalizeLabels"];
}
#pragma mark Services
@@ -143,7 +151,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
#pragma mark View methods
-- (IBAction)setStyle:(id)sender {
+- (IBAction)showStyle:(id)sender {
NSInteger tag;
if ([sender isKindOfClass:[NSMenuItem class]]) {
tag = [sender tag];
@@ -174,6 +182,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
NSAssert(NO, @"Cannot set style from control with tag %li", (long)tag);
break;
}
+ [self.undoManager removeAllActionsWithTarget:self];
self.mapView.styleURL = styleURL;
[self.window.toolbar validateVisibleItems];
}
@@ -195,6 +204,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
[alert addButtonWithTitle:@"Apply"];
[alert addButtonWithTitle:@"Cancel"];
if ([alert runModal] == NSAlertFirstButtonReturn) {
+ [self.undoManager removeAllActionsWithTarget:self];
self.mapView.styleURL = [NSURL URLWithString:textField.stringValue];
[[NSUserDefaults standardUserDefaults] setURL:self.mapView.styleURL forKey:@"MBXCustomStyleURL"];
[self.window.toolbar validateVisibleItems];
@@ -214,9 +224,164 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
}
- (IBAction)reload:(id)sender {
+ [self.undoManager removeAllActionsWithTarget:self];
[self.mapView reloadStyle:sender];
}
+/**
+ Show or hide the Layers sidebar.
+ */
+- (IBAction)toggleLayers:(id)sender {
+ BOOL isShown = ![self.splitView isSubviewCollapsed:self.splitView.arrangedSubviews.firstObject];
+ [NSAnimationContext runAnimationGroup:^(NSAnimationContext * _Nonnull context) {
+ context.allowsImplicitAnimation = YES;
+ [self.splitView setPosition:isShown ? 0 : 100 ofDividerAtIndex:0];
+ [self.window.toolbar validateVisibleItems];
+ } completionHandler:nil];
+}
+
+/**
+ Show or hide the selected layers.
+ */
+- (IBAction)toggleStyleLayers:(id)sender {
+ NSInteger clickedRow = self.styleLayersTableView.clickedRow;
+ NSIndexSet *indices = self.styleLayersTableView.selectedRowIndexes;
+ if (clickedRow >= 0 && ![indices containsIndex:clickedRow]) {
+ indices = [NSIndexSet indexSetWithIndex:clickedRow];
+ }
+ [self toggleStyleLayersAtArrangedObjectIndexes:indices];
+}
+
+- (void)toggleStyleLayersAtArrangedObjectIndexes:(NSIndexSet *)indices {
+ NS_ARRAY_OF(MGLStyleLayer *) *layers = [self.mapView.style.layers objectsAtIndexes:indices];
+ BOOL isVisible = layers.firstObject.visible;
+ [self.undoManager registerUndoWithTarget:self handler:^(MapDocument * _Nonnull target) {
+ [target toggleStyleLayersAtArrangedObjectIndexes:indices];
+ }];
+
+ if (!self.undoManager.undoing) {
+ NSString *actionName;
+ if (indices.count == 1) {
+ actionName = [NSString stringWithFormat:@"%@ Layer “%@”", isVisible ? @"Hide" : @"Show", layers.firstObject.identifier];
+ } else {
+ actionName = [NSString stringWithFormat:@"%@ %@ Layers", isVisible ? @"Hide" : @"Show",
+ [NSNumberFormatter localizedStringFromNumber:@(indices.count)
+ numberStyle:NSNumberFormatterDecimalStyle]];
+ }
+ [self.undoManager setActionIsDiscardable:YES];
+ [self.undoManager setActionName:actionName];
+ }
+
+ for (MGLStyleLayer *layer in layers) {
+ layer.visible = !isVisible;
+ }
+
+ NSIndexSet *columnIndices = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)];
+ [self.styleLayersTableView reloadDataForRowIndexes:indices columnIndexes:columnIndices];
+}
+
+- (IBAction)deleteStyleLayers:(id)sender {
+ NSInteger clickedRow = self.styleLayersTableView.clickedRow;
+ NSIndexSet *indices = self.styleLayersTableView.selectedRowIndexes;
+ if (clickedRow >= 0 && ![indices containsIndex:clickedRow]) {
+ indices = [NSIndexSet indexSetWithIndex:clickedRow];
+ }
+ [self deleteStyleLayersAtArrangedObjectIndexes:indices];
+}
+
+- (void)insertStyleLayers:(NS_ARRAY_OF(MGLStyleLayer *) *)layers atArrangedObjectIndexes:(NSIndexSet *)indices {
+ [self.undoManager registerUndoWithTarget:self handler:^(id _Nonnull target) {
+ [self deleteStyleLayersAtArrangedObjectIndexes:indices];
+ }];
+
+ if (!self.undoManager.undoing) {
+ NSString *actionName;
+ if (indices.count == 1) {
+ actionName = [NSString stringWithFormat:@"Add Layer “%@”", layers.firstObject.identifier];
+ } else {
+ actionName = [NSString stringWithFormat:@"Add %@ Layers",
+ [NSNumberFormatter localizedStringFromNumber:@(indices.count) numberStyle:NSNumberFormatterDecimalStyle]];
+ }
+ [self.undoManager setActionName:actionName];
+ }
+
+ [self.styleLayersArrayController insertObjects:layers atArrangedObjectIndexes:indices];
+}
+
+- (void)deleteStyleLayersAtArrangedObjectIndexes:(NSIndexSet *)indices {
+ NS_ARRAY_OF(MGLStyleLayer *) *layers = [self.mapView.style.layers objectsAtIndexes:indices];
+ [self.undoManager registerUndoWithTarget:self handler:^(id _Nonnull target) {
+ [self insertStyleLayers:layers atArrangedObjectIndexes:indices];
+ }];
+
+ if (!self.undoManager.undoing) {
+ NSString *actionName;
+ if (indices.count == 1) {
+ actionName = [NSString stringWithFormat:@"Delete Layer “%@”", layers.firstObject.identifier];
+ } else {
+ actionName = [NSString stringWithFormat:@"Delete %@ Layers",
+ [NSNumberFormatter localizedStringFromNumber:@(indices.count) numberStyle:NSNumberFormatterDecimalStyle]];
+ }
+ [self.undoManager setActionName:actionName];
+ }
+
+ [self.styleLayersArrayController removeObjectsAtArrangedObjectIndexes:indices];
+}
+
+- (IBAction)setLabelLanguage:(NSMenuItem *)sender {
+ _isLocalizingLabels = sender.tag;
+ [self updateLabels];
+}
+
+- (void)updateLabels {
+ NSString *preferredLanguageCode = self.preferredLanguageCode;
+ NSString *preferredNameToken = _isLocalizingLabels ? [NSString stringWithFormat:@"{name_%@}", preferredLanguageCode] : @"{name}";
+ NSRegularExpression *nameTokenExpression = [NSRegularExpression regularExpressionWithPattern:@"\\{name(?:_\\w{2})?\\}" options:0 error:NULL];
+
+ for (MGLSymbolStyleLayer *layer in self.mapView.style.layers) {
+ if (![layer isKindOfClass:[MGLSymbolStyleLayer class]]) {
+ continue;
+ }
+
+ if ([layer.textField isKindOfClass:[MGLStyleConstantValue class]]) {
+ NSString *textField = [(MGLStyleConstantValue<NSString *> *)layer.textField rawValue];
+ textField = [nameTokenExpression stringByReplacingMatchesInString:textField
+ options:0
+ range:NSMakeRange(0, textField.length)
+ withTemplate:preferredNameToken];
+ layer.textField = [MGLStyleValue<NSString *> valueWithRawValue:textField];
+ } else if ([layer.textField isKindOfClass:[MGLStyleFunction class]]) {
+ MGLStyleFunction *function = (MGLStyleFunction<NSString *> *)layer.textField;
+ NSMutableDictionary *stops = function.stops.mutableCopy;
+ [stops enumerateKeysAndObjectsUsingBlock:^(NSNumber *zoomLevel, MGLStyleConstantValue<NSString *> *stop, BOOL *done) {
+ NSString *textField = stop.rawValue;
+ textField = [nameTokenExpression stringByReplacingMatchesInString:textField
+ options:0
+ range:NSMakeRange(0, textField.length)
+ withTemplate:preferredNameToken];
+ stops[zoomLevel] = [MGLStyleValue<NSString *> valueWithRawValue:textField];
+ }];
+ function.stops = stops;
+ layer.textField = function;
+ }
+ }
+}
+
+- (NSString *)preferredLanguageCode {
+ // Languages supported by Mapbox Streets v10.
+ NSSet *supportedLanguages = [NSSet setWithObjects:@"en", @"es", @"fr", @"de", @"ru", @"zh", nil];
+ NSArray *preferredLanguages = [NSLocale preferredLanguages];
+
+ for (NSString *language in preferredLanguages) {
+ NSString *languageCode = [[NSLocale localeWithLocaleIdentifier:language] objectForKey:NSLocaleLanguageCode];
+ if ([supportedLanguages containsObject:languageCode]) {
+ return languageCode;
+ }
+ }
+
+ return @"en";
+}
+
- (void)applyPendingState {
if (_inheritedStyleURL) {
self.mapView.styleURL = _inheritedStyleURL;
@@ -563,7 +728,7 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
#pragma mark User interface validation
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
- if (menuItem.action == @selector(setStyle:)) {
+ if (menuItem.action == @selector(showStyle:)) {
NSURL *styleURL = self.mapView.styleURL;
NSCellStateValue state;
switch (menuItem.tag) {
@@ -607,6 +772,35 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
if (menuItem.action == @selector(reload:)) {
return YES;
}
+ if (menuItem.action == @selector(toggleLayers:)) {
+ BOOL isShown = ![self.splitView isSubviewCollapsed:self.splitView.arrangedSubviews.firstObject];
+ menuItem.title = isShown ? @"Hide Layers" : @"Show Layers";
+ return YES;
+ }
+ if (menuItem.action == @selector(toggleStyleLayers:)) {
+ NSInteger row = self.styleLayersTableView.clickedRow;
+ if (row == -1) {
+ row = self.styleLayersTableView.selectedRow;
+ }
+ if (row == -1) {
+ menuItem.title = @"Show";
+ } else {
+ BOOL isVisible = self.mapView.style.layers[row].visible;
+ menuItem.title = isVisible ? @"Hide" : @"Show";
+ }
+ return row != -1;
+ }
+ if (menuItem.action == @selector(deleteStyleLayers:)) {
+ return self.styleLayersTableView.clickedRow >= 0 || self.styleLayersTableView.selectedRow >= 0;
+ }
+ if (menuItem.action == @selector(setLabelLanguage:)) {
+ menuItem.state = menuItem.tag == _isLocalizingLabels ? NSOnState: NSOffState;
+ if (menuItem.tag) {
+ NSLocale *locale = [NSLocale localeWithLocaleIdentifier:[NSBundle mainBundle].developmentLocalization];
+ menuItem.title = [locale displayNameForKey:NSLocaleIdentifier value:self.preferredLanguageCode];
+ }
+ return YES;
+ }
if (menuItem.action == @selector(manipulateStyle:)) {
return YES;
}
@@ -722,7 +916,8 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
return NO;
}
- if (toolbarItem.action == @selector(showShareMenu:)) {
+ SEL action = toolbarItem.action;
+ if (action == @selector(showShareMenu:)) {
[(NSButton *)toolbarItem.view sendActionOn:NSLeftMouseDownMask];
if (![MGLAccountManager accessToken]) {
return NO;
@@ -731,14 +926,21 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
return ([styleURL.scheme isEqualToString:@"mapbox"]
&& [styleURL.pathComponents.firstObject isEqualToString:@"styles"]);
}
- if (toolbarItem.action == @selector(setStyle:)) {
+ if (action == @selector(showStyle:)) {
NSPopUpButton *popUpButton = (NSPopUpButton *)toolbarItem.view;
NSUInteger index = self.indexOfStyleInToolbarItem;
if (index == NSNotFound) {
- [popUpButton addItemWithTitle:@"Custom"];
- index = [popUpButton numberOfItems] - 1;
+ index = -1;
}
[popUpButton selectItemAtIndex:index];
+ if (index == -1) {
+ NSString *name = self.mapView.style.name;
+ popUpButton.title = name ?: @"Custom";
+ }
+ }
+ if (action == @selector(toggleLayers:)) {
+ BOOL isShown = ![self.splitView isSubviewCollapsed:self.splitView.arrangedSubviews.firstObject];
+ [(NSButton *)toolbarItem.view setState:isShown ? NSOnState : NSOffState];
}
return NO;
}
@@ -773,8 +975,22 @@ NS_ARRAY_OF(id <MGLAnnotation>) *MBXFlattenedShapes(NS_ARRAY_OF(id <MGLAnnotatio
}
}
+#pragma mark NSSplitViewDelegate methods
+
+- (BOOL)splitView:(NSSplitView *)splitView canCollapseSubview:(NSView *)subview {
+ return subview != self.mapView;
+}
+
+- (BOOL)splitView:(NSSplitView *)splitView shouldCollapseSubview:(NSView *)subview forDoubleClickOnDividerAtIndex:(NSInteger)dividerIndex {
+ return YES;
+}
+
#pragma mark MGLMapViewDelegate methods
+- (void)mapView:(MGLMapView *)mapView didFinishLoadingStyle:(MGLStyle *)style {
+ [self updateLabels];
+}
+
- (BOOL)mapView:(MGLMapView *)mapView annotationCanShowCallout:(id <MGLAnnotation>)annotation {
return YES;
}
diff --git a/platform/macos/app/StyleLayerIconTransformer.h b/platform/macos/app/StyleLayerIconTransformer.h
new file mode 100644
index 0000000000..1af1d512d6
--- /dev/null
+++ b/platform/macos/app/StyleLayerIconTransformer.h
@@ -0,0 +1,5 @@
+#import <Foundation/Foundation.h>
+
+@interface StyleLayerIconTransformer : NSValueTransformer
+
+@end
diff --git a/platform/macos/app/StyleLayerIconTransformer.m b/platform/macos/app/StyleLayerIconTransformer.m
new file mode 100644
index 0000000000..93f59abb3e
--- /dev/null
+++ b/platform/macos/app/StyleLayerIconTransformer.m
@@ -0,0 +1,38 @@
+#import "StyleLayerIconTransformer.h"
+
+#import <Mapbox/Mapbox.h>
+
+@implementation StyleLayerIconTransformer
+
++ (Class)transformedValueClass {
+ return [NSString class];
+}
+
++ (BOOL)allowsReverseTransformation {
+ return NO;
+}
+
+- (id)transformedValue:(MGLStyleLayer *)layer {
+ if ([layer isKindOfClass:[MGLBackgroundStyleLayer class]]) {
+ return [NSImage imageNamed:@"background"];
+ }
+ if ([layer isKindOfClass:[MGLCircleStyleLayer class]]) {
+ return [NSImage imageNamed:@"circle"];
+ }
+ if ([layer isKindOfClass:[MGLFillStyleLayer class]]) {
+ return [NSImage imageNamed:@"fill"];
+ }
+ if ([layer isKindOfClass:[MGLLineStyleLayer class]]) {
+ return [NSImage imageNamed:@"NSListViewTemplate"];
+ }
+ if ([layer isKindOfClass:[MGLRasterStyleLayer class]]) {
+ return [[NSWorkspace sharedWorkspace] iconForFileType:@"jpg"];
+ }
+ if ([layer isKindOfClass:[MGLSymbolStyleLayer class]]) {
+ return [NSImage imageNamed:@"symbol"];
+ }
+
+ return nil;
+}
+
+@end
diff --git a/platform/macos/app/resources/background.svg b/platform/macos/app/resources/background.svg
new file mode 100644
index 0000000000..39451e8b13
--- /dev/null
+++ b/platform/macos/app/resources/background.svg
@@ -0,0 +1,90 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ viewBox="0 0 16 16"
+ id="svg4148"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="background.svg"
+ inkscape:export-filename="/Users/mxn/Desktop/symbol.png"
+ inkscape:export-xdpi="90.000244"
+ inkscape:export-ydpi="90.000244">
+ <defs
+ id="defs4150">
+ <inkscape:path-effect
+ effect="spiro"
+ id="path-effect4877"
+ is_visible="true" />
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="10.48171"
+ inkscape:cx="8.5046012"
+ inkscape:cy="7.2814248"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ units="px"
+ inkscape:window-width="1280"
+ inkscape:window-height="751"
+ inkscape:window-x="0"
+ inkscape:window-y="1"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata4153">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 2.8621284,1037.3477 c 2.5635185,5.7342 4.4524268,0.068 4.4524268,0.068 l 0.067461,-5e-4 c 2.4960576,4.9921 4.1825828,-0.1349 4.1825828,-0.1349 l 0.02385,0 c 2.765902,5.5993 4.091271,0 4.091271,0 l 0.02385,0 c 3.170668,5.9366 4.293654,0 4.293654,0"
+ id="path4893"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -4.1486618,1041.2371 c 2.5635185,5.7342 4.45242682,0.068 4.45242682,0.068 l 0.067461,-5e-4 c 2.49605748,4.9921 4.18258278,-0.1349 4.18258278,-0.1349 l 0.023851,0 c 2.7659014,5.5993 4.0912704,0 4.0912704,0 l 0.02385,0 c 3.1706688,5.9366 4.2936548,0 4.2936548,0"
+ id="path4893-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m 3.7221911,1045.5303 c 2.5635186,5.7342 4.4524269,0.068 4.4524269,0.068 l 0.067461,-5e-4 c 2.496057,4.9921 4.182583,-0.1349 4.182583,-0.1349 l 0.02385,0 c 2.765901,5.5993 4.09127,0 4.09127,0 l 0.02385,0 c 3.170668,5.9366 4.293654,0 4.293654,0"
+ id="path4893-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -3.5762361,1049.3465 c 2.5635185,5.7342 4.4524268,0.068 4.4524268,0.068 l 0.067461,-5e-4 c 2.4960575,4.9921 4.1825828,-0.1349 4.1825828,-0.1349 l 0.023851,0 c 2.7659014,5.5993 4.0912702,0 4.0912702,0 l 0.02385,0 c 3.1706683,5.9366 4.2936543,0 4.2936543,0"
+ id="path4893-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ </g>
+</svg>
diff --git a/platform/macos/app/resources/circle.svg b/platform/macos/app/resources/circle.svg
new file mode 100644
index 0000000000..91e0b11990
--- /dev/null
+++ b/platform/macos/app/resources/circle.svg
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ viewBox="0 0 16 16"
+ id="svg4148"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="circle.svg"
+ inkscape:export-filename="/Users/mxn/Desktop/symbol.png"
+ inkscape:export-xdpi="90.000244"
+ inkscape:export-ydpi="90.000244">
+ <defs
+ id="defs4150" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="7.9195959"
+ inkscape:cx="3.8463784"
+ inkscape:cy="-0.92094419"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ units="px"
+ inkscape:window-width="1280"
+ inkscape:window-height="751"
+ inkscape:window-x="0"
+ inkscape:window-y="1"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata4153">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <circle
+ style="opacity:1;fill:none;fill-opacity:0;fill-rule:evenodd;stroke:#000000;stroke-width:1.49974895;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path4778"
+ cx="8"
+ cy="1044.3622"
+ r="7.2501254" />
+ </g>
+</svg>
diff --git a/platform/macos/app/resources/fill.svg b/platform/macos/app/resources/fill.svg
new file mode 100644
index 0000000000..7860a5fddb
--- /dev/null
+++ b/platform/macos/app/resources/fill.svg
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ viewBox="0 0 16 16"
+ id="svg4148"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="fill.svg"
+ inkscape:export-filename="/Users/mxn/Desktop/symbol.png"
+ inkscape:export-xdpi="90.000244"
+ inkscape:export-ydpi="90.000244">
+ <defs
+ id="defs4150" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="7.9195959"
+ inkscape:cx="0.31084444"
+ inkscape:cy="-0.92094419"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ units="px"
+ inkscape:window-width="1280"
+ inkscape:window-height="751"
+ inkscape:window-x="0"
+ inkscape:window-y="1"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata4153">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <rect
+ style="opacity:1;fill:#000000;fill-opacity:0.15686275;fill-rule:evenodd;stroke:#000000;stroke-width:1.37142861;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="rect4818"
+ width="14.628572"
+ height="14.628572"
+ x="0.68571424"
+ y="1037.048" />
+ </g>
+</svg>
diff --git a/platform/macos/app/resources/symbol.svg b/platform/macos/app/resources/symbol.svg
new file mode 100644
index 0000000000..68847cb50f
--- /dev/null
+++ b/platform/macos/app/resources/symbol.svg
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="16"
+ height="16"
+ viewBox="0 0 16 16"
+ id="svg4148"
+ version="1.1"
+ inkscape:version="0.91 r13725"
+ sodipodi:docname="symbol.svg"
+ inkscape:export-filename="/Users/mxn/Desktop/symbol.png"
+ inkscape:export-xdpi="90.000244"
+ inkscape:export-ydpi="90.000244">
+ <defs
+ id="defs4150" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="7.9195959"
+ inkscape:cx="3.8463784"
+ inkscape:cy="-0.92094419"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer1"
+ showgrid="false"
+ units="px"
+ inkscape:window-width="1280"
+ inkscape:window-height="751"
+ inkscape:window-x="0"
+ inkscape:window-y="1"
+ inkscape:window-maximized="1" />
+ <metadata
+ id="metadata4153">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(0,-1036.3622)">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000;stroke-width:1.45454013;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+ id="path5359"
+ d="m 13.062591,1042.4228 c 0,3.394 -5.0625908,9.2122 -5.0625908,9.2122 0,0 -5.0625898,-5.872 -5.0625898,-9.2122 0,-2.9629 2.2914879,-5.3333 5.0625898,-5.3333 2.7711018,0 5.0625908,2.3704 5.0625908,5.3333 z" />
+ </g>
+</svg>
diff --git a/platform/macos/macos.xcodeproj/project.pbxproj b/platform/macos/macos.xcodeproj/project.pbxproj
index edadff695b..ede5503fa3 100644
--- a/platform/macos/macos.xcodeproj/project.pbxproj
+++ b/platform/macos/macos.xcodeproj/project.pbxproj
@@ -40,6 +40,8 @@
35C5D84A1D6DD66D00E95907 /* NSCompoundPredicate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35C5D8461D6DD66D00E95907 /* NSCompoundPredicate+MGLAdditions.mm */; };
35D65C5A1D65AD5500722C23 /* NSDate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35D65C581D65AD5500722C23 /* NSDate+MGLAdditions.h */; };
35D65C5B1D65AD5500722C23 /* NSDate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35D65C591D65AD5500722C23 /* NSDate+MGLAdditions.mm */; };
+ 4032C5C51DE1FE930062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 4032C5B91DE1EEBA0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; };
+ 4032C5C61DE1FE9B0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4032C5C31DE1FE810062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm */; };
4049C2A51DB6CE7F00B3F799 /* MGLPointCollection.h in Headers */ = {isa = PBXBuildFile; fileRef = 4049C2A11DB6CE7800B3F799 /* MGLPointCollection.h */; settings = {ATTRIBUTES = (Public, ); }; };
4049C2AD1DB8020600B3F799 /* MGLPointCollection.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4049C2A71DB6D09B00B3F799 /* MGLPointCollection.mm */; };
408AA85B1DAEECFE00022900 /* MGLShape_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 408AA85A1DAEECF100022900 /* MGLShape_Private.h */; };
@@ -52,13 +54,14 @@
40ABDB561DB0022100372083 /* NSImage+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 405C03971DB0004E001AC280 /* NSImage+MGLAdditions.mm */; };
40B77E451DB11BC9003DA2FE /* NSArray+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 40B77E431DB11BB0003DA2FE /* NSArray+MGLAdditions.h */; };
40B77E461DB11BCD003DA2FE /* NSArray+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 40B77E421DB11BB0003DA2FE /* NSArray+MGLAdditions.mm */; };
+ 40E1601D1DF217D6005EA6D9 /* MGLStyleLayerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 40E1601B1DF216E6005EA6D9 /* MGLStyleLayerTests.m */; };
52BECB0A1CC5A26F009CD791 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 52BECB091CC5A26F009CD791 /* SystemConfiguration.framework */; };
5548BE781D09E718005DDE81 /* libmbgl-core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DAE6C3451CC31D1200DB3429 /* libmbgl-core.a */; };
558F18221D0B13B100123F46 /* libmbgl-loop.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 558F18211D0B13B000123F46 /* libmbgl-loop.a */; };
55D9B4B11D005D3900C1CCE2 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 55D9B4B01D005D3900C1CCE2 /* libz.tbd */; };
DA0CD58E1CF56F5800A5F5A5 /* MGLFeatureTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA0CD58D1CF56F5800A5F5A5 /* MGLFeatureTests.mm */; };
DA2207BC1DC076940002F84D /* MGLStyleValueTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */; };
- DA2DBBCB1D51E30A00D38FF9 /* MGLMapViewTests.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA2DBBCA1D51E30A00D38FF9 /* MGLMapViewTests.xib */; };
+ DA2DBBCB1D51E30A00D38FF9 /* MGLStyleLayerTests.xib in Resources */ = {isa = PBXBuildFile; fileRef = DA2DBBCA1D51E30A00D38FF9 /* MGLStyleLayerTests.xib */; };
DA35A2A41CC9EB1A00E826B2 /* MGLCoordinateFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */; settings = {ATTRIBUTES = (Public, ); }; };
DA35A2A61CC9EB2700E826B2 /* MGLCoordinateFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */; };
DA35A2A81CC9F41600E826B2 /* MGLCoordinateFormatterTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA35A2A71CC9F41600E826B2 /* MGLCoordinateFormatterTests.m */; };
@@ -85,7 +88,6 @@
DA87A9981DC9D88400810D09 /* MGLGeoJSONSourceTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA87A9961DC9D88400810D09 /* MGLGeoJSONSourceTests.mm */; };
DA87A9991DC9D88400810D09 /* MGLTileSetTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA87A9971DC9D88400810D09 /* MGLTileSetTests.mm */; };
DA87A99C1DC9D8DD00810D09 /* MGLGeoJSONSource_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA87A99B1DC9D8DD00810D09 /* MGLGeoJSONSource_Private.h */; };
- DA87A99D1DC9DB2E00810D09 /* MGLMapViewTests.m in Sources */ = {isa = PBXBuildFile; fileRef = DA2DBBC81D51E26600D38FF9 /* MGLMapViewTests.m */; };
DA87A99E1DC9DC2100810D09 /* MGLFilterTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35C5D84B1D6DD75B00E95907 /* MGLFilterTests.mm */; };
DA87A9A01DC9DC6200810D09 /* MGLValueEvaluator.h in Headers */ = {isa = PBXBuildFile; fileRef = DA87A99F1DC9DC6200810D09 /* MGLValueEvaluator.h */; };
DA87A9A11DC9DCB400810D09 /* MGLRuntimeStylingHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = DA8F257B1D51C5F40010E6B5 /* MGLRuntimeStylingHelper.m */; };
@@ -113,6 +115,7 @@
DA8F259C1D51CB000010E6B5 /* MGLStyleValue_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8F259B1D51CB000010E6B5 /* MGLStyleValue_Private.h */; };
DA8F25B21D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = DA8F25A61D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h */; };
DA8F25B31D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = DA8F25A71D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.mm */; };
+ DAA48EFD1D6A4731006A7E36 /* StyleLayerIconTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = DAA48EFC1D6A4731006A7E36 /* StyleLayerIconTransformer.m */; };
DAC2ABC51CC6D343006D18C4 /* MGLAnnotationImage_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = DAC2ABC41CC6D343006D18C4 /* MGLAnnotationImage_Private.h */; };
DACC22141CF3D3E200D220D9 /* MGLFeature.h in Headers */ = {isa = PBXBuildFile; fileRef = DACC22121CF3D3E200D220D9 /* MGLFeature.h */; settings = {ATTRIBUTES = (Public, ); }; };
DACC22151CF3D3E200D220D9 /* MGLFeature.mm in Sources */ = {isa = PBXBuildFile; fileRef = DACC22131CF3D3E200D220D9 /* MGLFeature.mm */; };
@@ -265,6 +268,10 @@
35C5D84B1D6DD75B00E95907 /* MGLFilterTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFilterTests.mm; sourceTree = "<group>"; };
35D65C581D65AD5500722C23 /* NSDate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+MGLAdditions.h"; sourceTree = "<group>"; };
35D65C591D65AD5500722C23 /* NSDate+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSDate+MGLAdditions.mm"; sourceTree = "<group>"; };
+ 4032C5B91DE1EEBA0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSValue+MGLStyleEnumAttributeAdditions.h"; sourceTree = "<group>"; };
+ 4032C5BA1DE1EECB0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h.ejs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "NSValue+MGLStyleEnumAttributeAdditions.h.ejs"; sourceTree = "<group>"; };
+ 4032C5C31DE1FE810062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSValue+MGLStyleEnumAttributeAdditions.mm"; sourceTree = "<group>"; };
+ 4032C5C71DE1FEAB0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm.ejs */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "NSValue+MGLStyleEnumAttributeAdditions.mm.ejs"; sourceTree = "<group>"; };
4049C2A11DB6CE7800B3F799 /* MGLPointCollection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLPointCollection.h; sourceTree = "<group>"; };
4049C2A71DB6D09B00B3F799 /* MGLPointCollection.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLPointCollection.mm; sourceTree = "<group>"; };
405C03961DB0004E001AC280 /* NSImage+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSImage+MGLAdditions.h"; sourceTree = "<group>"; };
@@ -278,6 +285,8 @@
408AA8611DAEED3300022900 /* MGLPolyline+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "MGLPolyline+MGLAdditions.h"; sourceTree = "<group>"; };
40B77E421DB11BB0003DA2FE /* NSArray+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSArray+MGLAdditions.mm"; sourceTree = "<group>"; };
40B77E431DB11BB0003DA2FE /* NSArray+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSArray+MGLAdditions.h"; sourceTree = "<group>"; };
+ 40E1601A1DF216E6005EA6D9 /* MGLStyleLayerTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyleLayerTests.h; sourceTree = "<group>"; };
+ 40E1601B1DF216E6005EA6D9 /* MGLStyleLayerTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLStyleLayerTests.m; sourceTree = "<group>"; };
52BECB091CC5A26F009CD791 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; };
5548BE791D0ACBB2005DDE81 /* libmbgl-loop-darwin.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmbgl-loop-darwin.a"; path = "cmake/Debug/libmbgl-loop-darwin.a"; sourceTree = "<group>"; };
5548BE7B1D0ACBBD005DDE81 /* libmbgl-loop-darwin.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmbgl-loop-darwin.a"; path = "cmake/Debug/libmbgl-loop-darwin.a"; sourceTree = "<group>"; };
@@ -287,9 +296,7 @@
DA0CD58D1CF56F5800A5F5A5 /* MGLFeatureTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFeatureTests.mm; path = ../../darwin/test/MGLFeatureTests.mm; sourceTree = "<group>"; };
DA2207BA1DC076930002F84D /* test-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "test-Bridging-Header.h"; sourceTree = "<group>"; };
DA2207BB1DC076940002F84D /* MGLStyleValueTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MGLStyleValueTests.swift; sourceTree = "<group>"; };
- DA2DBBC71D51E26600D38FF9 /* MGLMapViewTests.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MGLMapViewTests.h; path = ../darwin/test/MGLMapViewTests.h; sourceTree = SOURCE_ROOT; };
- DA2DBBC81D51E26600D38FF9 /* MGLMapViewTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLMapViewTests.m; path = ../darwin/test/MGLMapViewTests.m; sourceTree = SOURCE_ROOT; };
- DA2DBBCA1D51E30A00D38FF9 /* MGLMapViewTests.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MGLMapViewTests.xib; sourceTree = "<group>"; };
+ DA2DBBCA1D51E30A00D38FF9 /* MGLStyleLayerTests.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = MGLStyleLayerTests.xib; sourceTree = "<group>"; };
DA35A2A31CC9EB1A00E826B2 /* MGLCoordinateFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLCoordinateFormatter.h; sourceTree = "<group>"; };
DA35A2A51CC9EB2700E826B2 /* MGLCoordinateFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLCoordinateFormatter.m; sourceTree = "<group>"; };
DA35A2A71CC9F41600E826B2 /* MGLCoordinateFormatterTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MGLCoordinateFormatterTests.m; path = ../../darwin/test/MGLCoordinateFormatterTests.m; sourceTree = "<group>"; };
@@ -350,6 +357,8 @@
DA8F25B51D51D2240010E6B5 /* MGLRuntimeStylingTests.m.ejs */ = {isa = PBXFileReference; lastKnownFileType = text; path = MGLRuntimeStylingTests.m.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>"; };
+ DAA48EFB1D6A4731006A7E36 /* StyleLayerIconTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StyleLayerIconTransformer.h; sourceTree = "<group>"; };
+ DAA48EFC1D6A4731006A7E36 /* StyleLayerIconTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = StyleLayerIconTransformer.m; sourceTree = "<group>"; };
DAC2ABC41CC6D343006D18C4 /* MGLAnnotationImage_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLAnnotationImage_Private.h; sourceTree = "<group>"; };
DACC22121CF3D3E200D220D9 /* MGLFeature.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFeature.h; sourceTree = "<group>"; };
DACC22131CF3D3E200D220D9 /* MGLFeature.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFeature.mm; sourceTree = "<group>"; };
@@ -505,6 +514,8 @@
352742791D4C235C00A1ECE6 /* Categories */ = {
isa = PBXGroup;
children = (
+ 4032C5B91DE1EEBA0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h */,
+ 4032C5C31DE1FE810062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm */,
DA8F25A61D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.h */,
DA8F25A71D51CB270010E6B5 /* NSValue+MGLStyleAttributeAdditions.mm */,
);
@@ -580,6 +591,8 @@
DA839E9E1CC2E3400062CAFB /* MapDocument.xib */,
DAE6C2E91CC3050F00DB3429 /* OfflinePackNameValueTransformer.h */,
DAE6C2EA1CC3050F00DB3429 /* OfflinePackNameValueTransformer.m */,
+ DAA48EFB1D6A4731006A7E36 /* StyleLayerIconTransformer.h */,
+ DAA48EFC1D6A4731006A7E36 /* StyleLayerIconTransformer.m */,
DAE6C2EB1CC3050F00DB3429 /* TimeIntervalTransformer.h */,
DAE6C2EC1CC3050F00DB3429 /* TimeIntervalTransformer.m */,
DA839EA11CC2E3400062CAFB /* Assets.xcassets */,
@@ -635,9 +648,9 @@
DA8F257C1D51C5F40010E6B5 /* Layers */ = {
isa = PBXGroup;
children = (
+ 40E1601A1DF216E6005EA6D9 /* MGLStyleLayerTests.h */,
+ 40E1601B1DF216E6005EA6D9 /* MGLStyleLayerTests.m */,
DA2207BA1DC076930002F84D /* test-Bridging-Header.h */,
- DA2DBBC71D51E26600D38FF9 /* MGLMapViewTests.h */,
- DA2DBBC81D51E26600D38FF9 /* MGLMapViewTests.m */,
DA8F25741D51C5F40010E6B5 /* MGLFillStyleLayerTests.m */,
DA8F25751D51C5F40010E6B5 /* MGLRasterStyleLayerTests.m */,
DA8F25761D51C5F40010E6B5 /* MGLSymbolStyleLayerTests.m */,
@@ -646,7 +659,7 @@
DA8F25791D51C5F40010E6B5 /* MGLBackgroundStyleLayerTests.m */,
DA8F257A1D51C5F40010E6B5 /* MGLRuntimeStylingHelper.h */,
DA8F257B1D51C5F40010E6B5 /* MGLRuntimeStylingHelper.m */,
- DA2DBBCA1D51E30A00D38FF9 /* MGLMapViewTests.xib */,
+ DA2DBBCA1D51E30A00D38FF9 /* MGLStyleLayerTests.xib */,
);
name = Layers;
sourceTree = "<group>";
@@ -666,6 +679,8 @@
DA8F25B81D51D2280010E6B5 /* Foundation Templates */ = {
isa = PBXGroup;
children = (
+ 4032C5BA1DE1EECB0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h.ejs */,
+ 4032C5C71DE1FEAB0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm.ejs */,
DA8F25B51D51D2240010E6B5 /* MGLRuntimeStylingTests.m.ejs */,
DA8F25B61D51D2240010E6B5 /* MGLStyleLayer.h.ejs */,
DA8F25B71D51D2240010E6B5 /* MGLStyleLayer.mm.ejs */,
@@ -708,8 +723,8 @@
DAE6C36C1CC31E2A00DB3429 /* MGLGeometry_Private.h */,
DAE6C34C1CC31E0400DB3429 /* MGLGeometry.h */,
DAE6C36D1CC31E2A00DB3429 /* MGLGeometry.mm */,
- DAE6C36F1CC31E2A00DB3429 /* MGLMultiPoint_Private.h */,
DAE6C34E1CC31E0400DB3429 /* MGLMultiPoint.h */,
+ DAE6C36F1CC31E2A00DB3429 /* MGLMultiPoint_Private.h */,
DAE6C3701CC31E2A00DB3429 /* MGLMultiPoint.mm */,
DAE6C3521CC31E0400DB3429 /* MGLOverlay.h */,
DAE6C3531CC31E0400DB3429 /* MGLPointAnnotation.h */,
@@ -915,6 +930,7 @@
352742781D4C220900A1ECE6 /* MGLStyleValue.h in Headers */,
DAE6C35E1CC31E0400DB3429 /* MGLMultiPoint.h in Headers */,
35602BFF1D3EA9B40050646F /* MGLStyleLayer_Private.h in Headers */,
+ 4032C5C51DE1FE930062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.h in Headers */,
DAE6C3971CC31E2A00DB3429 /* NSBundle+MGLAdditions.h in Headers */,
DAED385F1D62CED700D7640F /* NSURL+MGLAdditions.h in Headers */,
DAD165741CF4CD7A001FF4B9 /* MGLShapeCollection.h in Headers */,
@@ -1134,7 +1150,7 @@
buildActionMask = 2147483647;
files = (
35724FC41D630502002A4AB4 /* amsterdam.geojson in Resources */,
- DA2DBBCB1D51E30A00D38FF9 /* MGLMapViewTests.xib in Resources */,
+ DA2DBBCB1D51E30A00D38FF9 /* MGLStyleLayerTests.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1145,6 +1161,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ DAA48EFD1D6A4731006A7E36 /* StyleLayerIconTransformer.m in Sources */,
DA839E9D1CC2E3400062CAFB /* MapDocument.m in Sources */,
DAE6C2ED1CC3050F00DB3429 /* DroppedPinAnnotation.m in Sources */,
DAE6C2EE1CC3050F00DB3429 /* LocationCoordinate2DTransformer.m in Sources */,
@@ -1176,6 +1193,7 @@
DAE6C3931CC31E2A00DB3429 /* MGLShape.mm in Sources */,
352742861D4C244700A1ECE6 /* MGLRasterSource.mm in Sources */,
DAE6C39D1CC31E2A00DB3429 /* NSString+MGLAdditions.m in Sources */,
+ 4032C5C61DE1FE9B0062E8BD /* NSValue+MGLStyleEnumAttributeAdditions.mm in Sources */,
DAE6C3941CC31E2A00DB3429 /* MGLStyle.mm in Sources */,
DAE6C3871CC31E2A00DB3429 /* MGLGeometry.mm in Sources */,
3527428E1D4C24AB00A1ECE6 /* MGLCircleStyleLayer.mm in Sources */,
@@ -1232,8 +1250,8 @@
DAE6C3D21CC34C9900DB3429 /* MGLGeometryTests.mm in Sources */,
DA87A9A41DCACC5000810D09 /* MGLSymbolStyleLayerTests.m in Sources */,
DAE6C3D51CC34C9900DB3429 /* MGLOfflineStorageTests.m in Sources */,
+ 40E1601D1DF217D6005EA6D9 /* MGLStyleLayerTests.m in Sources */,
DA87A9A61DCACC5000810D09 /* MGLCircleStyleLayerTests.m in Sources */,
- DA87A99D1DC9DB2E00810D09 /* MGLMapViewTests.m in Sources */,
DA87A99E1DC9DC2100810D09 /* MGLFilterTests.mm in Sources */,
DD58A4C91D822C6700E1F038 /* MGLExpressionTests.mm in Sources */,
DA87A9A71DCACC5000810D09 /* MGLBackgroundStyleLayerTests.m in Sources */,
diff --git a/platform/macos/src/MGLMapView.h b/platform/macos/src/MGLMapView.h
index 3dbbbe3d82..88745db212 100644
--- a/platform/macos/src/MGLMapView.h
+++ b/platform/macos/src/MGLMapView.h
@@ -89,6 +89,21 @@ IB_DESIGNABLE
#pragma mark Configuring the Map’s Appearance
/**
+ The style currently displayed in the receiver.
+
+ Unlike the `styleURL` property, this property is set to an object that allows
+ you to manipulate every aspect of the style locally.
+
+ @note The default styles provided by Mapbox contain sources and layers with
+ identifiers that will change over time. Applications that use APIs that
+ manipulate a style's sources and layers must first set the 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`.
+ */
+@property (nonatomic, readonly) MGLStyle *style;
+
+/**
URL of the style currently displayed in the receiver.
The URL may be a full HTTP or HTTPS URL, a Mapbox URL indicating the style’s
@@ -97,6 +112,9 @@ IB_DESIGNABLE
If you set this property to `nil`, the receiver will use the default style and
this property will automatically be set to that style’s URL.
+
+ If you want to modify the current style without replacing it outright, or if
+ you want to introspect individual style attributes, use the `style` property.
*/
@property (nonatomic, null_resettable) NSURL *styleURL;
@@ -782,6 +800,14 @@ IB_DESIGNABLE
To find out the layer names in a particular style, view the style in
<a href="https://www.mapbox.com/studio/">Mapbox Studio</a>.
+ @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 the
+ 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.
+
@param point A point expressed in the map view’s coordinate system.
@param styleLayerIdentifiers A set of strings that correspond to the names of
layers defined in the current style. Only the features contained in these
@@ -845,6 +871,14 @@ IB_DESIGNABLE
To find out the layer names in a particular style, view the style in
<a href="https://www.mapbox.com/studio/">Mapbox Studio</a>.
+ @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 the
+ 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.
+
@param rect A rectangle expressed in the map view’s coordinate system.
@param styleLayerIdentifiers A set of strings that correspond to the names of
layers defined in the current style. Only the features contained in these
@@ -926,10 +960,6 @@ IB_DESIGNABLE
*/
@property (nonatomic) MGLMapDebugMaskOptions debugMask;
-#pragma mark Runtime styling API
-
-- (MGLStyle *)style;
-
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/macos/src/MGLMapView.mm b/platform/macos/src/MGLMapView.mm
index 6442d73c71..90d2907d1a 100644
--- a/platform/macos/src/MGLMapView.mm
+++ b/platform/macos/src/MGLMapView.mm
@@ -34,6 +34,7 @@
#import <mbgl/util/chrono.hpp>
#import <mbgl/util/run_loop.hpp>
+#import <map>
#import <unordered_map>
#import <unordered_set>
@@ -109,6 +110,9 @@ enum { MGLAnnotationTagNotFound = UINT32_MAX };
/// the annotation itself.
typedef std::unordered_map<MGLAnnotationTag, MGLAnnotationContext> MGLAnnotationTagContextMap;
+/// Mapping from an annotation object to an annotation tag.
+typedef std::map<id<MGLAnnotation>, MGLAnnotationTag> MGLAnnotationObjectTagMap;
+
/// Returns an NSImage for the default marker image.
NSImage *MGLDefaultMarkerImage() {
NSString *path = [[NSBundle mgl_frameworkBundle] pathForResource:MGLDefaultStyleMarkerSymbolName
@@ -140,13 +144,15 @@ public:
NSString *imageReuseIdentifier;
};
-@interface MGLMapView () <NSPopoverDelegate, MGLMultiPointDelegate>
+@interface MGLMapView () <NSPopoverDelegate, MGLMultiPointDelegate, NSGestureRecognizerDelegate>
@property (nonatomic, readwrite) NSSegmentedControl *zoomControls;
@property (nonatomic, readwrite) NSSlider *compass;
@property (nonatomic, readwrite) NSImageView *logoView;
@property (nonatomic, readwrite) NSView *attributionView;
+@property (nonatomic, readwrite) MGLStyle *style;
+
/// Mapping from reusable identifiers to annotation images.
@property (nonatomic) NS_MUTABLE_DICTIONARY_OF(NSString *, MGLAnnotationImage *) *annotationImagesByIdentifier;
/// Currently shown popover representing the selected annotation.
@@ -165,12 +171,14 @@ public:
NSPanGestureRecognizer *_panGestureRecognizer;
NSMagnificationGestureRecognizer *_magnificationGestureRecognizer;
NSRotationGestureRecognizer *_rotationGestureRecognizer;
+ NSClickGestureRecognizer *_singleClickRecognizer;
double _scaleAtBeginningOfGesture;
CLLocationDirection _directionAtBeginningOfGesture;
CGFloat _pitchAtBeginningOfGesture;
BOOL _didHideCursorDuringGesture;
MGLAnnotationTagContextMap _annotationContextsByAnnotationTag;
+ MGLAnnotationObjectTagMap _annotationTagsByAnnotation;
MGLAnnotationTag _selectedAnnotationTag;
MGLAnnotationTag _lastSelectedAnnotationTag;
/// Size of the rectangle formed by unioning the maximum slop area around every annotation image.
@@ -180,6 +188,8 @@ public:
BOOL _wantsToolTipRects;
/// True if any annotation images that have custom cursors have been installed.
BOOL _wantsCursorRects;
+ /// True if a willChange notification has been issued for shape annotation layers and a didChange notification is pending.
+ BOOL _isChangingAnnotationLayers;
// Cached checks for delegate method implementations that may be called from
// MGLMultiPointDelegate methods.
@@ -290,6 +300,7 @@ public:
// Set up annotation management and selection state.
_annotationImagesByIdentifier = [NSMutableDictionary dictionary];
_annotationContextsByAnnotationTag = {};
+ _annotationTagsByAnnotation = {};
_selectedAnnotationTag = MGLAnnotationTagNotFound;
_lastSelectedAnnotationTag = MGLAnnotationTagNotFound;
_annotationsNearbyLastClick = {};
@@ -405,9 +416,10 @@ public:
_panGestureRecognizer.delaysKeyEvents = YES;
[self addGestureRecognizer:_panGestureRecognizer];
- NSClickGestureRecognizer *clickGestureRecognizer = [[NSClickGestureRecognizer alloc] initWithTarget:self action:@selector(handleClickGesture:)];
- clickGestureRecognizer.delaysPrimaryMouseButtonEvents = NO;
- [self addGestureRecognizer:clickGestureRecognizer];
+ _singleClickRecognizer = [[NSClickGestureRecognizer alloc] initWithTarget:self action:@selector(handleClickGesture:)];
+ _singleClickRecognizer.delaysPrimaryMouseButtonEvents = NO;
+ _singleClickRecognizer.delegate = self;
+ [self addGestureRecognizer:_singleClickRecognizer];
NSClickGestureRecognizer *rightClickGestureRecognizer = [[NSClickGestureRecognizer alloc] initWithTarget:self action:@selector(handleRightClickGesture:)];
rightClickGestureRecognizer.buttonMask = 0x2;
@@ -577,7 +589,7 @@ public:
if (_isTargetingInterfaceBuilder) {
return;
}
-
+
// Default to Streets.
if (!styleURL) {
// An access token is required to load any default style, including
@@ -589,7 +601,10 @@ public:
}
styleURL = styleURL.mgl_URLByStandardizingScheme;
+ [self willChangeValueForKey:@"style"];
+ _style = [[MGLStyle alloc] initWithMapView:self];
_mbglMap->setStyleURL(styleURL.absoluteString.UTF8String);
+ [self didChangeValueForKey:@"style"];
}
- (IBAction)reloadStyle:(__unused id)sender {
@@ -849,6 +864,10 @@ public:
}
case mbgl::MapChangeDidFinishLoadingMap:
{
+ [self.style willChangeValueForKey:@"sources"];
+ [self.style didChangeValueForKey:@"sources"];
+ [self.style willChangeValueForKey:@"layers"];
+ [self.style didChangeValueForKey:@"layers"];
if ([self.delegate respondsToSelector:@selector(mapViewDidFinishLoadingMap:)]) {
[self.delegate mapViewDidFinishLoadingMap:self];
}
@@ -888,6 +907,10 @@ public:
case mbgl::MapChangeDidFinishRenderingFrame:
case mbgl::MapChangeDidFinishRenderingFrameFullyRendered:
{
+ if (_isChangingAnnotationLayers) {
+ _isChangingAnnotationLayers = NO;
+ [self.style didChangeValueForKey:@"layers"];
+ }
if ([self.delegate respondsToSelector:@selector(mapViewDidFinishRenderingFrame:fullyRendered:)]) {
BOOL fullyRendered = change == mbgl::MapChangeDidFinishRenderingFrameFullyRendered;
[self.delegate mapViewDidFinishRenderingFrame:self fullyRendered:fullyRendered];
@@ -896,6 +919,11 @@ public:
}
case mbgl::MapChangeDidFinishLoadingStyle:
{
+ [self.style willChangeValueForKey:@"name"];
+ [self.style willChangeValueForKey:@"sources"];
+ [self.style didChangeValueForKey:@"sources"];
+ [self.style willChangeValueForKey:@"layers"];
+ [self.style didChangeValueForKey:@"layers"];
if ([self.delegate respondsToSelector:@selector(mapView:didFinishLoadingStyle:)])
{
[self.delegate mapView:self didFinishLoadingStyle:self.style];
@@ -1520,6 +1548,20 @@ public:
return nil;
}
+#pragma mark NSGestureRecognizerDelegate methods
+- (BOOL)gestureRecognizer:(NSGestureRecognizer *)gestureRecognizer shouldAttemptToRecognizeWithEvent:(NSEvent *)event {
+ if (gestureRecognizer == _singleClickRecognizer) {
+ if (!self.selectedAnnotation) {
+ NSPoint gesturePoint = [self convertPoint:[event locationInWindow] fromView:nil];
+ MGLAnnotationTag hitAnnotationTag = [self annotationTagAtPoint:gesturePoint persistingResults:NO];
+ if (hitAnnotationTag == MGLAnnotationTagNotFound) {
+ return NO;
+ }
+ }
+ }
+ return YES;
+}
+
#pragma mark Keyboard events
- (void)keyDown:(NSEvent *)event {
@@ -1641,7 +1683,11 @@ public:
for (auto const& annotationTag: annotationTags)
{
- MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag[annotationTag];
+ if (!_annotationContextsByAnnotationTag.count(annotationTag))
+ {
+ continue;
+ }
+ MGLAnnotationContext annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
[annotations addObject:annotationContext.annotation];
}
@@ -1663,16 +1709,11 @@ public:
/// Returns the annotation tag assigned to the given annotation. Relatively expensive.
- (MGLAnnotationTag)annotationTagForAnnotation:(id <MGLAnnotation>)annotation {
- if (!annotation) {
+ if (!annotation || _annotationTagsByAnnotation.count(annotation) == 0) {
return MGLAnnotationTagNotFound;
}
- for (auto &pair : _annotationContextsByAnnotationTag) {
- if (pair.second.annotation == annotation) {
- return pair.first;
- }
- }
- return MGLAnnotationTagNotFound;
+ return _annotationTagsByAnnotation.at(annotation);
}
- (void)addAnnotation:(id <MGLAnnotation>)annotation {
@@ -1693,6 +1734,12 @@ public:
for (id <MGLAnnotation> annotation in annotations) {
NSAssert([annotation conformsToProtocol:@protocol(MGLAnnotation)], @"Annotation does not conform to MGLAnnotation");
+ // adding the same annotation object twice is a no-op
+ if ([self.annotations containsObject:annotation])
+ {
+ continue;
+ }
+
if ([annotation isKindOfClass:[MGLMultiPoint class]]) {
// The multipoint knows how to style itself (with the map view’s help).
MGLMultiPoint *multiPoint = (MGLMultiPoint *)annotation;
@@ -1700,10 +1747,12 @@ public:
continue;
}
+ _isChangingAnnotationLayers = YES;
MGLAnnotationTag annotationTag = _mbglMap->addAnnotation([multiPoint annotationObjectWithDelegate:self]);
MGLAnnotationContext context;
context.annotation = annotation;
_annotationContextsByAnnotationTag[annotationTag] = context;
+ _annotationTagsByAnnotation[annotation] = annotationTag;
[(NSObject *)annotation addObserver:self forKeyPath:@"coordinates" options:0 context:(void *)(NSUInteger)annotationTag];
} else if (![annotation isKindOfClass:[MGLMultiPolyline class]]
@@ -1741,6 +1790,7 @@ public:
context.annotation = annotation;
context.imageReuseIdentifier = annotationImage.reuseIdentifier;
_annotationContextsByAnnotationTag[annotationTag] = context;
+ _annotationTagsByAnnotation[annotation] = annotationTag;
if ([annotation isKindOfClass:[NSObject class]]) {
NSAssert(![annotation isKindOfClass:[MGLMultiPoint class]], @"Point annotation should not be MGLMultiPoint.");
@@ -1755,6 +1805,9 @@ public:
}
[self didChangeValueForKey:@"annotations"];
+ if (_isChangingAnnotationLayers) {
+ [self.style willChangeValueForKey:@"layers"];
+ }
[self updateAnnotationTrackingAreas];
}
@@ -1827,6 +1880,7 @@ public:
}
_annotationContextsByAnnotationTag.erase(annotationTag);
+ _annotationTagsByAnnotation.erase(annotation);
if ([annotation isKindOfClass:[NSObject class]] &&
![annotation isKindOfClass:[MGLMultiPoint class]]) {
@@ -1835,10 +1889,14 @@ public:
[(NSObject *)annotation removeObserver:self forKeyPath:@"coordinates" context:(void *)(NSUInteger)annotationTag];
}
+ _isChangingAnnotationLayers = YES;
_mbglMap->removeAnnotation(annotationTag);
}
[self didChangeValueForKey:@"annotations"];
+ if (_isChangingAnnotationLayers) {
+ [self.style willChangeValueForKey:@"layers"];
+ }
[self updateAnnotationTrackingAreas];
}
@@ -2192,13 +2250,6 @@ public:
#pragma mark - Runtime styling
-- (MGLStyle *)style
-{
- MGLStyle *style = [[MGLStyle alloc] init];
- style.mapView = self;
- return style;
-}
-
- (mbgl::Map *)mbglMap
{
return _mbglMap;
@@ -2582,11 +2633,19 @@ public:
}
void activate() override {
+ if (activationCount++) {
+ return;
+ }
+
MGLOpenGLLayer *layer = (MGLOpenGLLayer *)nativeView.layer;
[layer.openGLContext makeCurrentContext];
}
void deactivate() override {
+ if (--activationCount) {
+ return;
+ }
+
[NSOpenGLContext clearCurrentContext];
}
@@ -2616,6 +2675,9 @@ private:
/// The current framebuffer of the NSOpenGLLayer we are painting to.
GLint fbo = 0;
+
+ /// The reference counted count of activation calls
+ NSUInteger activationCount = 0;
};
@end
diff --git a/platform/macos/src/Mapbox.h b/platform/macos/src/Mapbox.h
index cfddfe6e89..73b8624be0 100644
--- a/platform/macos/src/Mapbox.h
+++ b/platform/macos/src/Mapbox.h
@@ -46,4 +46,5 @@ FOUNDATION_EXPORT const unsigned char MapboxVersionString[];
#import "MGLTilePyramidOfflineRegion.h"
#import "MGLTypes.h"
#import "NSValue+MGLAdditions.h"
+#import "NSValue+MGLStyleEnumAttributeAdditions.h"
#import "MGLStyleValue.h"
diff --git a/src/mbgl/map/map.cpp b/src/mbgl/map/map.cpp
index 8577002c04..40f4e91c9d 100644
--- a/src/mbgl/map/map.cpp
+++ b/src/mbgl/map/map.cpp
@@ -837,6 +837,10 @@ AnnotationIDs Map::queryPointAnnotations(const ScreenBox& box) {
#pragma mark - Style API
+std::vector<style::Source*> Map::getSources() {
+ return impl->style ? impl->style->getSources() : std::vector<style::Source*>();
+}
+
style::Source* Map::getSource(const std::string& sourceID) {
if (impl->style) {
impl->styleMutated = true;
@@ -860,7 +864,11 @@ std::unique_ptr<Source> Map::removeSource(const std::string& sourceID) {
return nullptr;
}
-style::Layer* Map::getLayer(const std::string& layerID) {
+std::vector<style::Layer*> Map::getLayers() {
+ return impl->style ? impl->style->getLayers() : std::vector<style::Layer*>();
+}
+
+Layer* Map::getLayer(const std::string& layerID) {
if (impl->style) {
impl->styleMutated = true;
return impl->style->getLayer(layerID);
diff --git a/src/mbgl/style/style.cpp b/src/mbgl/style/style.cpp
index 44843ce8b7..f16e8f1856 100644
--- a/src/mbgl/style/style.cpp
+++ b/src/mbgl/style/style.cpp
@@ -175,6 +175,15 @@ std::vector<const Layer*> Style::getLayers() const {
return result;
}
+std::vector<Layer*> Style::getLayers() {
+ std::vector<Layer*> result;
+ result.reserve(layers.size());
+ for (auto& layer : layers) {
+ result.push_back(layer.get());
+ }
+ return result;
+}
+
std::vector<std::unique_ptr<Layer>>::const_iterator Style::findLayer(const std::string& id) const {
return std::find_if(layers.begin(), layers.end(), [&](const auto& layer) {
return layer->baseImpl->id == id;
@@ -333,6 +342,24 @@ void Style::recalculate(float z, const TimePoint& timePoint, MapMode mode) {
}
}
+std::vector<const Source*> Style::getSources() const {
+ std::vector<const Source*> result;
+ result.reserve(sources.size());
+ for (const auto& source : sources) {
+ result.push_back(source.get());
+ }
+ return result;
+}
+
+std::vector<Source*> Style::getSources() {
+ std::vector<Source*> result;
+ result.reserve(sources.size());
+ for (auto& source : sources) {
+ result.push_back(source.get());
+ }
+ return result;
+}
+
Source* Style::getSource(const std::string& id) const {
const auto it = std::find_if(sources.begin(), sources.end(), [&](const auto& source) {
return source->getID() == id;
diff --git a/src/mbgl/style/style.hpp b/src/mbgl/style/style.hpp
index 4ad540acd1..d46e80e8bf 100644
--- a/src/mbgl/style/style.hpp
+++ b/src/mbgl/style/style.hpp
@@ -64,11 +64,14 @@ public:
return lastError;
}
+ std::vector<const Source*> getSources() const;
+ std::vector<Source*> getSources();
Source* getSource(const std::string& id) const;
void addSource(std::unique_ptr<Source>);
std::unique_ptr<Source> removeSource(const std::string& sourceID);
std::vector<const Layer*> getLayers() const;
+ std::vector<Layer*> getLayers();
Layer* getLayer(const std::string& id) const;
Layer* addLayer(std::unique_ptr<Layer>,
optional<std::string> beforeLayerID = {});