summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJesse Bounds <jesse@rebounds.net>2017-02-08 12:27:12 -0800
committerGitHub <noreply@github.com>2017-02-08 12:27:12 -0800
commit06a8ed79598beae923b795dea711834b4775f6b0 (patch)
tree65afbaaf19bee1e7ed7508d6c3b49ee88aa6fc37
parent6d69686a12f5fb3761e3318410f5626198d0b92c (diff)
downloadqtlocation-mapboxgl-06a8ed79598beae923b795dea711834b4775f6b0.tar.gz
Add back MGLStyleFunction and re-document MGLStyleValue (#7943)
[ios, macos] Add back MGLStyleFunction and re-document MGLStyleValue
-rw-r--r--platform/darwin/src/MGLStyleValue.h322
-rw-r--r--platform/darwin/src/MGLStyleValue.mm104
-rw-r--r--platform/darwin/src/MGLStyleValue_Private.h19
-rw-r--r--platform/darwin/test/MGLStyleValueTests.swift70
4 files changed, 428 insertions, 87 deletions
diff --git a/platform/darwin/src/MGLStyleValue.h b/platform/darwin/src/MGLStyleValue.h
index c8ec08b6a0..1ae8a67861 100644
--- a/platform/darwin/src/MGLStyleValue.h
+++ b/platform/darwin/src/MGLStyleValue.h
@@ -30,9 +30,10 @@ typedef NS_ENUM(NSUInteger, MGLInterpolationMode) {
The `MGLStyleValue` class itself represents a class cluster. Under the hood, a
particular `MGLStyleValue` object may be either an `MGLStyleConstantValue` to
- represent a constant value or an `MGLStyleFunction` to represent a value
- function. Do not initialize an `MGLStyleValue` object directly; instead, use
- one of the class factory methods to create an `MGLStyleValue` object.
+ represent a constant value or one of the concrete subclasses of
+ `MGLStyleFunction` to represent a value function. Do not initialize an
+ `MGLStyleValue` object directly; instead, use one of the class factory methods
+ to create an `MGLStyleValue` object.
The `MGLStyleValue` class takes a generic parameter `T` that indicates the
Foundation class being wrapped by this class. Common values for `T` include:
@@ -62,32 +63,68 @@ MGL_EXPORT
#pragma mark Function values
/**
- Creates and returns an `MGLStyleFunction` object representing a linear zoom
- level function with any number of stops.
+ Creates and returns an `MGLCameraStyleFunction` object representing a linear camera
+ function with one or more stops.
@param stops A dictionary associating zoom levels with style values.
- @return An `MGLStyleFunction` object with the given stops.
+ @return An `MGLCameraStyleFunction` object with the given stops.
*/
-+ (instancetype)valueWithStops:(NSDictionary<NSNumber *, MGLStyleValue<T> *> *)stops __attribute__((deprecated("Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]")));
++ (instancetype)valueWithStops:(NS_DICTIONARY_OF(NSNumber *, MGLStyleValue<T> *) *)stops __attribute__((deprecated("Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]")));
/**
- Creates and returns an `MGLStyleFunction` object representing a zoom level
- function with an exponential interpolation base and any number of stops.
+ Creates and returns an `MGLCameraStyleFunction` object representing a camera
+ function with an exponential interpolation base and one or more stops.
@param interpolationBase The exponential base of the interpolation curve.
@param stops A dictionary associating zoom levels with style values.
- @return An `MGLStyleFunction` object with the given interpolation base and stops.
+ @return An `MGLCameraStyleFunction` object with the given interpolation base and stops.
*/
-+ (instancetype)valueWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary<NSNumber *, MGLStyleValue<T> *> *)stops __attribute__((deprecated("Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]")));
++ (instancetype)valueWithInterpolationBase:(CGFloat)interpolationBase stops:(NS_DICTIONARY_OF(NSNumber *, MGLStyleValue<T> *) *)stops __attribute__((deprecated("Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]")));
-// TODO: API docs
-+ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode cameraStops:(NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)stops options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
+/**
+ Creates and returns an `MGLCameraStyleFunction` object representing a camera function
+ with one or more stops.
+
+ @param interpolationMode The mode used to interpolate property values between
+ map zoom level changes.
+ @param cameraStops A dictionary associating zoom levels with style values.
+ @param options A dictionary containing `MGLStyleFunctionOption` values that
+ specify how a function is applied.
+ @return An `MGLCameraStyleFunction` object with the given interpolation mode,
+ camera stops, and options.
+ */
++ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode cameraStops:(NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)cameraStops options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
-// TODO: API docs
-+ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode sourceStops:(nullable NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)stops attributeName:(NSString *)attributeName options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
+/**
+ Creates and returns an `MGLSourceStyleFunction` object representing a source function.
+
+ @param interpolationMode The mode used to interpolate property values over a
+ range of feature attribute values.
+ @param sourceStops A dictionary associating feature attributes with style values.
+ @param attributeName Specifies the feature attribute to take as the function
+ input.
+ @param options A dictionary containing `MGLStyleFunctionOption` values that
+ specify how a function is applied.
+ @return An `MGLSourceStyleFunction` object with the given interpolation mode,
+ source stops, attribute name, and options.
+ */
++ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode sourceStops:(nullable NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)sourceStops attributeName:(NSString *)attributeName options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
-// TODO: API docs
-+ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode compositeStops:(NS_DICTIONARY_OF(id, NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *) *)stops attributeName:(NSString *)attributeName options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
+/**
+ Creates and returns an `MGLCompositeStyleFunction` object representing a composite
+ function.
+
+ @param interpolationMode The mode used to interpolate property values over a
+ range of feature attribute values for each outer zoom level.
+ @param sourceStops A dictionary associating feature attributes with style values.
+ @param attributeName Specifies the feature attribute to take as the function
+ input.
+ @param options A dictionary containing `MGLStyleFunctionOption` values that
+ specify how a function is applied.
+ @return An `MGLCompositeStyleFunction` object with the given interpolation mode,
+ composite stops, attribute name, and options.
+ */
++ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode compositeStops:(NS_DICTIONARY_OF(id, NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *) *)compositeStops attributeName:(NSString *)attributeName options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
@end
@@ -135,77 +172,258 @@ MGL_EXPORT
@end
+/**
+ An `MGLStyleFunction` is a is an abstract superclass for functions that are
+ defined by an `MGLCameraStyleFunction`, `MGLSourceStyleFunction`, or
+ `MGLCompositeStyleFunction` object.
+
+ Do not create instances of this class directly, and do not create your own
+ subclasses of this class. Instead, use one of the class factory methods in
+ `MGLStyleValue` to create instances of the following concrete subclasses:
+ `MGLCameraStyleFunction`, `MGLSourceStyleFunction`, and
+ `MGLCompositeStyleFunction`.
+
+ The `MGLStyleFunction` class takes a generic parameter `T` that indicates the
+ Foundation class being wrapped by this class.
+ */
MGL_EXPORT
-@interface MGLCameraStyleFunction<T> : MGLStyleValue<T>
+@interface MGLStyleFunction<T> : MGLStyleValue<T>
-// TODO: API docs
-+ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)stops options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
+#pragma mark Creating a Style Function
-// TODO: API docs
-- (instancetype)initWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)stops options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options NS_DESIGNATED_INITIALIZER;
+/**
+ Creates and returns an `MGLCameraStyleFunction` object representing a camera
+ function with a linear interpolation curve.
-// TODO: API docs
+ @note Do not create function instances using this method unless it is required
+ for backwards compatiblity with your application code.
+
+ @param stops A dictionary associating zoom levels with style values.
+ @return An `MGLCameraStyleFunction` object with the given stops.
+ */
++ (instancetype)functionWithStops:(NS_DICTIONARY_OF(NSNumber *, MGLStyleValue<T> *) *)stops __attribute__((deprecated("Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]")));
+
+/**
+ Creates and returns an `MGLCameraStyleFunction` object representing a camera
+ function with an interpolation curve controlled by the provided interpolation
+ base.
+
+ @note Do not create function instances using this method unless it is required
+ for backwards compatiblity with your application code.
+
+ @param interpolationBase The exponential base of the interpolation curve.
+ @param stops A dictionary associating zoom levels with style values.
+ @return An `MGLCameraStyleFunction` object with the given interpolation base and stops.
+ */
++ (instancetype)functionWithInterpolationBase:(CGFloat)interpolationBase stops:(NS_DICTIONARY_OF(NSNumber *, MGLStyleValue<T> *) *)stops __attribute__((deprecated("Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]")));
+
+#pragma mark Initializing a Style Function
+
+/**
+ Returns an `MGLStyleFunction` object representing a camera function. If the
+ function is set as a style layer property value, it will be interpreted
+ as a camera function with an interpolation curve controlled by the provided
+ interpolation base.
+
+ @note Do not create instances of `MGLStyleFunction` unless it is required for
+ backwards compatiblity with your application code. You should create and use
+ instances of `MGLCameraStyleFunction` to specify how properties will
+ be visualized at different zoom levels.
+
+ @param interpolationBase The exponential base of the interpolation curve.
+ @param stops A dictionary associating zoom levels with style values.
+ @return An `MGLStyleFunction` object with the given interpolation base and stops.
+ */
+- (instancetype)initWithInterpolationBase:(CGFloat)interpolationBase stops:(NS_DICTIONARY_OF(NSNumber *, MGLStyleValue<T> *) *)stops __attribute__((deprecated("Use +[MGLStyleValue valueWithInterpolationMode:cameraStops:options:]")));
+
+#pragma mark Accessing the Parameters of a Function
+
+/**
+ The modes used to interpolate property values between map zoom level changes or
+ over a range of feature attribute values.
+ */
@property (nonatomic) MGLInterpolationMode interpolationMode;
-// TODO: API docs
-@property (nonatomic, copy) NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *stops;
+/**
+ A dictionary associating zoom levels with style values.
+ */
+@property (nonatomic, copy, nullable) NSDictionary *stops;
-// TODO: API docs
+/**
+ The exponential interpolation base of the function’s interpolation curve.
+
+ @note This property specifies the exponential base of the interpolation curve
+ of `MGLCameraStyleFunction` and `MGLSourceStyleFunction` functions that use
+ a `MGLInterpolationModeExponential` `interpolationMode`. Otherwise, it is
+ ignored.
+ */
@property (nonatomic) CGFloat interpolationBase;
@end
-@compatibility_alias MGLStyleFunction MGLCameraStyleFunction;
+/**
+ An `MGLCameraStyleFunction` is a value function defining a style value that changes
+ as the zoom level changes. The layout and paint attribute properties of an
+ `MGLStyleLayer` object can be set to `MGLCameraStyleFunction` objects. Use a camera
+ function to create the illusion of depth and control data density.
+ The `MGLCameraStyleFunction` class takes a generic parameter `T` that indicates the
+ Foundation class being wrapped by this class.
+ */
MGL_EXPORT
-@interface MGLSourceStyleFunction<T> : MGLStyleValue<T>
+@interface MGLCameraStyleFunction<T> : MGLStyleFunction<T>
-// TODO: API docs
-+ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(nullable NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)stops attributeName:(NSString *)attributeName options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
+#pragma mark Creating a Camera Function
-// TODO: API docs
-- (instancetype)initWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(nullable NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)stops attributeName:(NSString *)attributeName options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options NS_DESIGNATED_INITIALIZER;
+/**
+ Creates and returns an `MGLCameraStyleFunction` object representing a camera
+ function with one or more stops.
-// TODO: API docs
-@property (nonatomic) MGLInterpolationMode interpolationMode;
+ @param interpolationMode The mode used to interpolate property values between
+ map zoom level changes.
+ @param stops A dictionary associating zoom levels with style values.
+ @param options A dictionary containing `MGLStyleFunctionOption` values that
+ specify how a function is applied.
+ @return An `MGLCameraStyleFunction` object with the given interpolation mode,
+ camera stops, and options.
+ */
++ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)stops options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
-// TODO: API docs
+#pragma mark Accessing the Parameters of a Camera Function
+
+/**
+ A dictionary associating zoom levels with style values.
+
+ Each of the function’s stops is represented by one key-value pair in the
+ dictionary. Each key in the dictionary is an `NSNumber` object containing a
+ floating-point zoom level. Each value in the dictionary is an `MGLStyleValue`
+ object containing the value of the style attribute when the map is at the
+ associated zoom level. An `MGLStyleFunction` object may not be used recursively
+ as a stop value.
+ */
+@property (nonatomic, copy) NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *stops;
+
+@end
+
+/**
+ An `MGLSourceStyleFunction` is a value function defining a style value that
+ changes with its properties. The layout and paint attribute properties of an
+ `MGLStyleLayer` object can be set to `MGLSourceStyleFunction` objects.
+ Use source functions to visually differentate types of features within the same
+ layer or create data visualizations.
+
+ The `MGLSourceStyleFunction` class takes a generic parameter `T` that indicates the
+ Foundation class being wrapped by this class.
+ */
+MGL_EXPORT
+@interface MGLSourceStyleFunction<T> : MGLStyleFunction<T>
+
+#pragma mark Creating a Source Function
+
+/**
+ Creates and returns an `MGLSourceStyleFunction` object representing a source
+ function.
+
+ @param interpolationMode The mode used to interpolate property values over a
+ range of feature attribute values.
+ @param sourceStops A dictionary associating feature attributes with style values.
+ @param attributeName Specifies the feature attribute to take as the function
+ input.
+ @param options A dictionary containing `MGLStyleFunctionOption` values that
+ specify how a function is applied.
+ @return An `MGLSourceStyleFunction` object with the given interpolation mode,
+ source stops, attribute name, and options.
+*/
++ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(nullable NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)stops attributeName:(NSString *)attributeName options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
+
+#pragma mark Accessing the Parameters of a Source Function
+
+/**
+ A string that specifies the feature attribute key whose value be used as the function
+ input.
+*/
@property (nonatomic, copy) NSString *attributeName;
-// TODO: API docs
+/**
+ A dictionary associating attribute values with style values.
+
+ Each of the function’s stops is represented by one key-value pair in the
+ dictionary. Each key in the dictionary is an object representing a feature
+ attribute key or interpolation stop. Each value in the dictionary is an
+ `MGLStyleValue` object containing the value to use when the function is given
+ the associated attribute key. An `MGLStyleFunction` object may not be used
+ recursively as a stop value.
+ */
@property (nonatomic, copy, nullable) NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *stops;
-// TODO: API docs
+/**
+ An `MGLStyleValue` object containing the default value to use when there is
+ no input to provide to the function.
+ */
@property (nonatomic, nullable) MGLStyleValue<T> *defaultValue;
-// TODO: API docs
-@property (nonatomic) CGFloat interpolationBase;
-
@end
+/**
+ An `MGLCompositeStyleFunction` is a value function defining a style value that
+ changes with the feature attributes at each map zoom level. The layout and paint
+ attribute properties of an `MGLStyleLayer` object can be set to
+ `MGLCompositeStyleFunction` objects. Use composite functions to allow the
+ appearance of a map feature to change with both its attributes and the map zoom
+ level.
+
+ The `MGLCompositeStyleFunction` class takes a generic parameter `T` that indicates the
+ Foundation class being wrapped by this class.
+ */
MGL_EXPORT
-@interface MGLCompositeStyleFunction<T> : MGLStyleValue<T>
+@interface MGLCompositeStyleFunction<T> : MGLStyleFunction<T>
-// TODO: API docs
-+ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NS_DICTIONARY_OF(id, NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *) *)stops attributeName:(NSString *)attributeName options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
+#pragma mark Creating a Composite Function
-- (instancetype)initWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NS_DICTIONARY_OF(id, NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *) *)stops attributeName:(NSString *)attributeName options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options NS_DESIGNATED_INITIALIZER;
+/**
+ Creates and returns an `MGLCompositeStyleFunction` object representing a composite
+ function.
+
+ @param interpolationMode The mode used to interpolate property values over a
+ range of feature attribute values for each outer zoom level.
+ @param sourceStops A dictionary associating feature attributes with style values.
+ @param attributeName Specifies the feature attribute to take as the function
+ input.
+ @param options A dictionary containing `MGLStyleFunctionOption` values that
+ specify how a function is applied.
+ @return An `MGLCompositeStyleFunction` object with the given interpolation mode,
+ composite stops, attribute name, and options.
+ */
++ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NS_DICTIONARY_OF(id, NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *) *)stops attributeName:(NSString *)attributeName options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
-// TODO: API docs
-@property (nonatomic) MGLInterpolationMode interpolationMode;
+#pragma mark Accessing the Parameters of a Composite Function
-// TODO: API docs
+/**
+ A string that specifies the feature attribute key whose value be used as the function
+ input.
+ */
@property (nonatomic, copy) NSString *attributeName;
-// TODO: API docs
+/**
+ A dictionary associating attribute values with style values.
+
+ Each of the function’s stops is represented by one key-value pair in the
+ dictionary. Each key in the dictionary is an `NSNumber` object containing a
+ floating-point zoom level. Each value in the dictionary is an inner nested
+ dictionary. Each key in the nested dictionary is an object representing a feature
+ attribute key or interpolation stop. Each value in the nested dictionary is an
+ `MGLStyleValue` object containing the value to use when the function is given
+ the associated attribute key. An `MGLStyleFunction` object may not be used
+ recursively as a value inside the nested dictionary.
+ */
@property (nonatomic, copy) NS_DICTIONARY_OF(id, NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *) *stops;
-// TODO: API docs
+/**
+ An `MGLStyleValue` object containing the default value to use when there is
+ no input to provide to the function.
+ */
@property (nonatomic, nullable) MGLStyleValue<T> *defaultValue;
-// TODO: API docs
-@property (nonatomic) CGFloat interpolationBase;
-
@end
NS_ASSUME_NONNULL_END
diff --git a/platform/darwin/src/MGLStyleValue.mm b/platform/darwin/src/MGLStyleValue.mm
index 1a8e6edeab..020dc27d6a 100644
--- a/platform/darwin/src/MGLStyleValue.mm
+++ b/platform/darwin/src/MGLStyleValue.mm
@@ -17,16 +17,16 @@ const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunc
return [MGLCameraStyleFunction functionWithInterpolationMode:MGLInterpolationModeExponential stops:stops options:nil];
}
-+ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode cameraStops:(NSDictionary *)stops options:(NSDictionary *)options {
- return [MGLCameraStyleFunction functionWithInterpolationMode:interpolationMode stops:stops options:options];
++ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode cameraStops:(NSDictionary *)cameraStops options:(NSDictionary *)options {
+ return [MGLCameraStyleFunction functionWithInterpolationMode:interpolationMode stops:cameraStops options:options];
}
-+ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode sourceStops:(NSDictionary *)stops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
- return [MGLSourceStyleFunction functionWithInterpolationMode:interpolationMode stops:stops attributeName:attributeName options:options];
++ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode sourceStops:(NSDictionary *)sourceStops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
+ return [MGLSourceStyleFunction functionWithInterpolationMode:interpolationMode stops:sourceStops attributeName:attributeName options:options];
}
-+ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode compositeStops:(NSDictionary *)stops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
- return [MGLCompositeStyleFunction functionWithInterpolationMode:interpolationMode stops:stops attributeName:attributeName options:options];
++ (instancetype)valueWithInterpolationMode:(MGLInterpolationMode)interpolationMode compositeStops:(NSDictionary *)compositeStops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
+ return [MGLCompositeStyleFunction functionWithInterpolationMode:interpolationMode stops:compositeStops attributeName:attributeName options:options];
}
@end
@@ -62,16 +62,63 @@ const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunc
@end
+@implementation MGLStyleFunction
+
++ (instancetype)functionWithStops:(NSDictionary *)stops {
+ return [MGLCameraStyleFunction functionWithInterpolationMode:MGLInterpolationModeExponential stops:stops options:nil];
+}
+
++ (instancetype)functionWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops {
+ return [MGLCameraStyleFunction functionWithInterpolationMode:MGLInterpolationModeExponential stops:stops options:@{MGLStyleFunctionOptionInterpolationBase: @(interpolationBase)}];
+}
+
+- (instancetype)init {
+ if (self = [super init]) {
+ self.interpolationBase = 1.0;
+ self.stops = @{};
+ }
+ return self;
+}
+
+- (instancetype)initWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops {
+ if (self = [super init]) {
+ self.interpolationBase = interpolationBase;
+ self.stops = stops;
+ }
+ return self;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@: %p, \
+ stops = %@, \
+ interpolationBase = %f>",
+ NSStringFromClass([self class]), (void *)self,
+ self.stops,
+ self.interpolationBase];
+}
+
+- (BOOL)isEqual:(MGLStyleFunction *)other {
+ return ([other isKindOfClass:[self class]]
+ && [other.stops isEqualToDictionary:self.stops]
+ && other.interpolationBase == self.interpolationBase);
+}
+
+- (NSUInteger)hash {
+ return self.stops.hash + @(self.interpolationBase).hash;
+}
+
+@end
+
@implementation MGLCameraStyleFunction
-@synthesize interpolationMode = _interpolationMode;
+@dynamic stops;
+ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops options:(NSDictionary *)options {
return [[self alloc] initWithInterpolationMode:interpolationMode stops:stops options:options];
}
-- (instancetype)init {
- return [self initWithInterpolationMode:MGLInterpolationModeExponential stops:@{} options:nil];
+- (instancetype)initWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops {
+ return [self initWithInterpolationMode:MGLInterpolationModeExponential stops:stops options:@{MGLStyleFunctionOptionInterpolationBase: @(interpolationBase)}];
}
- (instancetype)initWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops options:(NSDictionary *)options {
@@ -82,14 +129,13 @@ const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunc
}
if (self == [super init]) {
- _interpolationMode = interpolationMode;
- _stops = stops;
- _interpolationBase = 1.0;
+ self.interpolationMode = interpolationMode;
+ self.stops = stops;
if ([options.allKeys containsObject:MGLStyleFunctionOptionInterpolationBase]) {
if ([options[MGLStyleFunctionOptionInterpolationBase] isKindOfClass:[NSNumber class]]) {
NSNumber *value = (NSNumber *)options[MGLStyleFunctionOptionInterpolationBase];
- _interpolationBase = [value floatValue];
+ self.interpolationBase = [value floatValue];
} else {
[NSException raise:NSInvalidArgumentException format:@"Interpolation base must be an NSNumber that represents a CGFloat."];
}
@@ -117,29 +163,28 @@ const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunc
}
- (NSUInteger)hash {
- return self.interpolationMode + self.stops.hash + self.interpolationBase;
+ return @(self.interpolationMode).hash + self.stops.hash + @(self.interpolationBase).hash;
}
@end
@implementation MGLSourceStyleFunction
-@synthesize interpolationMode = _interpolationMode;
+@dynamic stops;
+ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
return [[self alloc] initWithInterpolationMode:interpolationMode stops:stops attributeName:attributeName options:options];
}
-- (instancetype)init {
- return [self initWithInterpolationMode:MGLInterpolationModeExponential stops:nil attributeName:@"" options:nil];
+- (instancetype)initWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops {
+ return [self initWithInterpolationMode:MGLInterpolationModeExponential stops:stops attributeName:@"" options:@{MGLStyleFunctionOptionInterpolationBase: @(interpolationBase)}];
}
- (instancetype)initWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
if (self == [super init]) {
- _interpolationMode = interpolationMode;
- _stops = stops;
+ self.interpolationMode = interpolationMode;
+ self.stops = stops;
_attributeName = attributeName;
- _interpolationBase = 1.0;
if ([options.allKeys containsObject:MGLStyleFunctionOptionDefaultValue]) {
if ([options[MGLStyleFunctionOptionDefaultValue] isKindOfClass:[MGLStyleValue class]]) {
@@ -153,7 +198,7 @@ const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunc
if ([options.allKeys containsObject:MGLStyleFunctionOptionInterpolationBase]) {
if ([options[MGLStyleFunctionOptionInterpolationBase] isKindOfClass:[NSNumber class]]) {
NSNumber *value = (NSNumber *)options[MGLStyleFunctionOptionInterpolationBase];
- _interpolationBase = [value floatValue];
+ self.interpolationBase = [value floatValue];
} else {
[NSException raise:NSInvalidArgumentException format:@"Interpolation base must be an NSNumber that represents a CGFloat."];
}
@@ -188,29 +233,28 @@ const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunc
}
- (NSUInteger)hash {
- return self.interpolationMode + self.stops.hash + self.attributeName.hash + self.defaultValue.hash + self.interpolationBase;
+ return @(self.interpolationMode).hash + self.stops.hash + self.attributeName.hash + self.defaultValue.hash + @(self.interpolationBase).hash;
}
@end
@implementation MGLCompositeStyleFunction
-@synthesize interpolationMode = _interpolationMode;
+@dynamic stops;
+ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
return [[self alloc] initWithInterpolationMode:interpolationMode stops:stops attributeName:attributeName options:options];
}
-- (instancetype)init {
- return [self initWithInterpolationMode:MGLInterpolationModeExponential stops:@{} attributeName:@"" options:nil];
+- (instancetype)initWithInterpolationBase:(CGFloat)interpolationBase stops:(NSDictionary *)stops {
+ return [self initWithInterpolationMode:MGLInterpolationModeExponential stops:stops attributeName:@"" options:@{MGLStyleFunctionOptionInterpolationBase: @(interpolationBase)}];
}
- (instancetype)initWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NSDictionary *)stops attributeName:(NSString *)attributeName options:(NSDictionary *)options {
if (self == [super init]) {
- _interpolationMode = interpolationMode;
- _stops = stops;
+ self.interpolationMode = interpolationMode;
+ self.stops = stops;
_attributeName = attributeName;
- _interpolationBase = 1.0;
if ([options.allKeys containsObject:MGLStyleFunctionOptionDefaultValue]) {
if ([options[MGLStyleFunctionOptionDefaultValue] isKindOfClass:[MGLStyleValue class]]) {
@@ -224,7 +268,7 @@ const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunc
if ([options.allKeys containsObject:MGLStyleFunctionOptionInterpolationBase]) {
if ([options[MGLStyleFunctionOptionInterpolationBase] isKindOfClass:[NSNumber class]]) {
NSNumber *value = (NSNumber *)options[MGLStyleFunctionOptionInterpolationBase];
- _interpolationBase = [value floatValue];
+ self.interpolationBase = [value floatValue];
} else {
[NSException raise:NSInvalidArgumentException format:@"Interpolation base must be an NSNumber that represents a CGFloat."];
}
@@ -258,7 +302,7 @@ const MGLStyleFunctionOption MGLStyleFunctionOptionDefaultValue = @"MGLStyleFunc
}
- (NSUInteger)hash {
- return self.interpolationMode + self.stops.hash + self.attributeName.hash + self.interpolationBase;
+ return @(self.interpolationMode).hash + self.stops.hash + self.attributeName.hash + @(self.interpolationBase).hash;
}
@end
diff --git a/platform/darwin/src/MGLStyleValue_Private.h b/platform/darwin/src/MGLStyleValue_Private.h
index b4354d7d16..03a8f242cf 100644
--- a/platform/darwin/src/MGLStyleValue_Private.h
+++ b/platform/darwin/src/MGLStyleValue_Private.h
@@ -60,6 +60,9 @@ public:
// a deprecated MGLStyleValue method (that used to create an MGLStyleFunction) to create a function
// for properties that are piecewise-constant (i.e. enum, bool, string)
return toMBGLIntervalCameraFunction(cameraStyleFunction);
+ } else if ([value isMemberOfClass:[MGLStyleFunction class]]) {
+ MGLStyleFunction<ObjCType> *styleFunction = (MGLStyleFunction<ObjCType> *)value;
+ return toMBGLIntervalCameraFunction(styleFunction);
} else if (value) {
[NSException raise:@"MGLAbstractClassException" format:
@"The style value %@ cannot be applied to the style. "
@@ -81,6 +84,9 @@ public:
if ([value isKindOfClass:[MGLStyleConstantValue class]]) {
return toMBGLConstantValue((MGLStyleConstantValue<ObjCType> *)value);
+ } else if ([value isMemberOfClass:[MGLStyleFunction class]]) {
+ MGLStyleFunction<ObjCType> *styleFunction = (MGLStyleFunction<ObjCType> *)value;
+ return toMBGLExponentialCameraFunction(styleFunction);
} else if ([value isKindOfClass:[MGLCameraStyleFunction class]]) {
MGLCameraStyleFunction<ObjCType> *cameraStyleFunction = (MGLCameraStyleFunction<ObjCType> *)value;
switch (cameraStyleFunction.interpolationMode) {
@@ -247,6 +253,9 @@ public:
return {};
}
return {};
+ } else if ([value isMemberOfClass:[MGLStyleFunction class]]) {
+ MGLStyleFunction<ObjCType> *styleFunction = (MGLStyleFunction<ObjCType> *)value;
+ return toMBGLExponentialCameraFunction(styleFunction);
} else if (value) {
[NSException raise:@"MGLAbstractClassException" format:
@"The style value %@ cannot be applied to the style. "
@@ -308,9 +317,9 @@ private: // Private utilities for converting from mgl to mbgl values
return mbglValue;
}
- mbgl::style::CameraFunction<MBGLType> toMBGLExponentialCameraFunction(MGLCameraStyleFunction<ObjCType> *cameraStyleFunction) {
+ mbgl::style::CameraFunction<MBGLType> toMBGLExponentialCameraFunction(MGLStyleFunction<ObjCType> *styleFunction) {
__block std::map<float, MBGLType> stops = {};
- [cameraStyleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleValue<ObjCType> * _Nonnull stopValue, BOOL * _Nonnull stop) {
+ [styleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleValue<ObjCType> * _Nonnull stopValue, BOOL * _Nonnull stop) {
NSCAssert([stopValue isKindOfClass:[MGLStyleValue class]], @"Stops should be MGLStyleValues");
auto mbglStopValue = toPropertyValue(stopValue);
NSCAssert(mbglStopValue.isConstant(), @"Stops must be constant");
@@ -318,15 +327,15 @@ private: // Private utilities for converting from mgl to mbgl values
}];
// Camera function with Exponential stops
- mbgl::style::ExponentialStops<MBGLType> exponentialStops = {stops, (float)cameraStyleFunction.interpolationBase};
+ mbgl::style::ExponentialStops<MBGLType> exponentialStops = {stops, (float)styleFunction.interpolationBase};
mbgl::style::CameraFunction<MBGLType> cameraFunction = {exponentialStops};
return cameraFunction;
}
- mbgl::style::CameraFunction<MBGLType> toMBGLIntervalCameraFunction(MGLCameraStyleFunction<ObjCType> *cameraStyleFunction) {
+ mbgl::style::CameraFunction<MBGLType> toMBGLIntervalCameraFunction(MGLStyleFunction<ObjCType> *styleFunction) {
__block std::map<float, MBGLType> stops = {};
- [cameraStyleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleValue<ObjCType> * _Nonnull stopValue, BOOL * _Nonnull stop) {
+ [styleFunction.stops enumerateKeysAndObjectsUsingBlock:^(NSNumber * _Nonnull zoomKey, MGLStyleValue<ObjCType> * _Nonnull stopValue, BOOL * _Nonnull stop) {
NSCAssert([stopValue isKindOfClass:[MGLStyleValue class]], @"Stops should be MGLStyleValues");
auto mbglStopValue = toPropertyValue(stopValue);
NSCAssert(mbglStopValue.isConstant(), @"Stops must be constant");
diff --git a/platform/darwin/test/MGLStyleValueTests.swift b/platform/darwin/test/MGLStyleValueTests.swift
index 066232329f..afdc2ef9a3 100644
--- a/platform/darwin/test/MGLStyleValueTests.swift
+++ b/platform/darwin/test/MGLStyleValueTests.swift
@@ -38,6 +38,7 @@ extension MGLStyleValueTests {
func testDeprecatedFunctions() {
let shapeSource = MGLShapeSource(identifier: "test", shape: nil, options: nil)
let symbolStyleLayer = MGLSymbolStyleLayer(identifier: "symbolLayer", source: shapeSource)
+ let circleStyleLayer = MGLCircleStyleLayer(identifier: "circleLayer", source: shapeSource)
// deprecated function, stops with float values
let iconHaloBlurStyleValue = MGLStyleValue<NSNumber>(interpolationBase: 1.0, stops: [1: MGLStyleValue(rawValue: 0),
@@ -63,6 +64,66 @@ extension MGLStyleValueTests {
options: nil
)
XCTAssertEqual(symbolStyleLayer.iconAllowsOverlap, expectedIconAllowsOverlapStyleValue)
+
+ ///
+ // creating and using MGLStyleFunctions directly
+ ///
+
+ let circleRadiusStops: [NSNumber: MGLStyleValue<NSNumber>] = [
+ 0: MGLStyleValue(rawValue: 10),
+ 20: MGLStyleValue(rawValue: 5)
+ ]
+ let circleRadiusFunction = MGLStyleFunction<NSNumber>(
+ interpolationBase: 1.0,
+ stops: circleRadiusStops
+ )
+ circleStyleLayer.circleRadius = circleRadiusFunction
+ let expectedCircleRadiusFunction = MGLStyleValue<NSNumber>(
+ interpolationMode: .exponential,
+ cameraStops:
+ circleRadiusStops,
+ options: nil
+ )
+ // setting a data driven property to an MGLStyleFunction should return an exponential camera function
+ XCTAssertEqual(circleStyleLayer.circleRadius, expectedCircleRadiusFunction)
+
+ var circleTranslationOne = CGVector(dx: 100, dy: 0)
+ let circleTranslationValueOne = NSValue(bytes: &circleTranslationOne, objCType: "{CGVector=dd}")
+ var circleTranslationTwo = CGVector(dx: 0, dy: 0)
+ let circleTranslationValueTwo = NSValue(bytes: &circleTranslationTwo, objCType: "{CGVector=dd}")
+
+ let circleTranslationStops: [NSNumber: MGLStyleValue<NSValue>] = [
+ 0: MGLStyleValue<NSValue>(rawValue: circleTranslationValueOne),
+ 10: MGLStyleValue<NSValue>(rawValue: circleTranslationValueTwo)
+ ]
+ let circleTranslationFunction = MGLStyleFunction<NSValue>(
+ interpolationBase: 1.0,
+ stops: circleTranslationStops
+ )
+ circleStyleLayer.circleTranslation = circleTranslationFunction
+ let expectedCircleTranslationFunction = MGLStyleValue<NSValue>(
+ interpolationMode: .exponential,
+ cameraStops: circleTranslationStops,
+ options: nil
+ )
+ // setting a non-data driven, interpolatable property to an MGLStyleFunction should return an exponential camera function
+ XCTAssertEqual(circleStyleLayer.circleTranslation, expectedCircleTranslationFunction)
+
+ let iconOptionalStops: [NSNumber: MGLStyleValue<NSNumber>] = [
+ 0: MGLStyleValue(rawValue: false),
+ 20: MGLStyleValue(rawValue: true)
+ ]
+ let iconOptionalFunction = MGLStyleFunction(
+ interpolationBase: 1.0,
+ stops: iconOptionalStops
+ )
+ symbolStyleLayer.iconOptional = iconOptionalFunction
+ let expectedIconOptionalFunction = MGLStyleValue(
+ interpolationMode: .interval,
+ cameraStops: iconOptionalStops,
+ options: nil
+ )
+ XCTAssertEqual(symbolStyleLayer.iconOptional, expectedIconOptionalFunction)
}
func testFunctionsWithNonDataDrivenProperties() {
@@ -293,6 +354,15 @@ extension MGLStyleValueTests {
}
}
+ // get value back as base class
+ if let returnedCircleRadius = circleStyleLayer.circleRadius as? MGLStyleFunction<NSNumber> {
+ if let returnedStops = returnedCircleRadius.stops as NSDictionary? as? [NSNumber: [NSNumber: MGLStyleValue<NSNumber>]] {
+ let lhs: MGLStyleValue<NSNumber> = returnedStops[0]!.values.first!
+ let rhs: MGLStyleValue<NSNumber> = radiusCompositeExponentialOrIntervalStops[0]!.values.first!
+ XCTAssertEqual(lhs, rhs)
+ }
+ }
+
// data-driven, composite function with inner interval color stop values nested in outer camera stops
let expectedCompositeIntervalValue = MGLStyleValue<NSNumber>(
interpolationMode: .interval,