diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2016-12-03 15:36:42 -0800 |
---|---|---|
committer | Minh Nguyễn <mxn@1ec5.org> | 2016-12-03 15:36:42 -0800 |
commit | 3503c0e7679d5802068fc2ab2420b575a8ae2fc7 (patch) | |
tree | d1cfdd3ca2f2fb9761466a61e77d82d8f6b76002 /platform/darwin | |
parent | 84038832e45c2445b43b39ccb2f9e29c8646dac0 (diff) | |
parent | 9eb7f88b2c292d322a104c4580c3ef29958b628b (diff) | |
download | qtlocation-mapboxgl-3503c0e7679d5802068fc2ab2420b575a8ae2fc7.tar.gz |
Merge branch 'release-ios-v3.4.0' into 1ec5-release-ios-v3.4.0-beta.4-master
Diffstat (limited to 'platform/darwin')
60 files changed, 3285 insertions, 1208 deletions
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)]); } |