Skip to content
This repository has been archived by the owner on Aug 8, 2023. It is now read-only.

Add back MGLStyleFunction and re-document MGLStyleValue #7943

Merged
merged 13 commits into from
Feb 8, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
317 changes: 270 additions & 47 deletions platform/darwin/src/MGLStyleValue.h
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -62,32 +63,70 @@ 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:]")));

/**
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:]")));

// 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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember to use the NS_…_OF macros until we drop iOS 8 support.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like we forgot to do this in the 3.4.0 release. In fbb8068 and 3b90d85 I updated the deprecated methods and everything in the resurrected MGLStyleFunction to use the macro. The only use of NSDictionary (with no lightweight generic attributes) in MGLStyleValue now is for the stops property of MGLStyleFunction for reasons already discussed in this PR.


// 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 made up of one or more outer stops interpreted as a camera function
with a single inner stop at each zoom level that is interpreted as a source
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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If each stop is “interpreted as a source function”, should the type of compositeStops be NSDictionary<id, NSDictionary<id, MGLSourceStyleFunction<T> *> *> *?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was me doing a poor job of trying to clarify the opposite: "composite" in this case means a composite of stops dictionaries not functions (see discussion in #7596 (comment)). In d46559a, I punted on trying to explain this in the class factory method in favor of the explanation in the MGLCompositeStyleFunction stops property


@end

Expand Down Expand Up @@ -135,77 +174,261 @@ 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>

// TODO: API docs
+ (instancetype)functionWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)stops options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options;
@interface MGLStyleFunction<T> : MGLStyleValue<T>

// 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;
#pragma mark Accessing the Parameters of a Function

// TODO: API docs
/**
The modes used to interpolate property values between map zoom level changes or
over a range of feature attribute values.
*/
@property (nonatomic) MGLInterpolationMode interpolationMode;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we avoid effectively adding an interpolationMode property to MGLStyleFunction that would only sometimes be applicable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In ee89e94 I removed it in MGLStyleFunction and added it back to the concrete subclasses. This sort of makes sense because an MGLStyleFunction technically does not (did not) have an interpolation mode. In the future, we should add the property back to MGLStyleFunction because every actual function class does have an interpolation mode.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

every actual function class does have an interpolation mode

Ah, I misunderstood. In that case, it’s fine (and preferable) to have it in MGLStyleFunction to avoid duplication.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah. For now, it'll be a bit of a lie, but still reasonable.

MGLStyleFunction's interpolation mode will be exponential even though it did not have such a concept before in 3.4.x. However, any MGLStyleFunction instance that is put to use in 3.5.0 is treated like a camera function with an exponential interpolation mode so I feel ok about that. I'll put it back on MGLStyleFunction.


// TODO: API docs
@property (nonatomic, copy) NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *stops;
/**
A dictionary associating zoom levels with style values.
*/
@property (nonatomic, copy) NSDictionary *stops;

// TODO: API docs
/**
The exponential interpolation base of the function’s interpolation curve.
*/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Document the fact that interpolationBase may not apply to all style functions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@property (nonatomic) CGFloat interpolationBase;

@end
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For backwards compatibility, MGLStyleFunction also needs the initializers that it had in v3.4.0. These initializers can be marked as deprecated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will probably look a bit strange no matter what we do. I think 406e647 is a workable solution until a semver bump when we can more officially make this class abstract.

The initializers have been brought back and an actual instance of MGLStyleFunction is created and returned if you use them. The conversion methods have been updated to coerce MGLStyleFunction instances into MGLCameraStyleFunction instances with the appropriate interpolation mode. However, documentation attempts to point developers to the MGLStyleValue class factory methods to avoid all of this.


@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 zoom
level function to create the illusion of depth and control data density.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

“Zoom level functions” are now known as “camera functions”.


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
#pragma mark Creating a Camera Function

/**
Creates and returns an `MGLCameraStyleFunction` object representing a zoom level
function with one or more stops.

@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;

#pragma mark Initializing a Camera Function

/**
Returns an `MGLCameraStyleFunction` object representing a zoom level
function with one or more stops.

@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)initWithInterpolationMode:(MGLInterpolationMode)interpolationMode stops:(NS_DICTIONARY_OF(id, MGLStyleValue<T> *) *)stops options:(nullable NS_DICTIONARY_OF(MGLStyleFunctionOption, id) *)options NS_DESIGNATED_INITIALIZER;

#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;

// TODO: API docs
#pragma mark Initializing a Source Function

/**
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)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;

// TODO: API docs
@property (nonatomic) MGLInterpolationMode interpolationMode;
#pragma mark Accessing the Parameters of a Source 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 object representing a feature
attribute key. 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
#pragma mark Creating a Composite Function

/**
Creates and returns an `MGLCompositeStyleFunction` object representing a composite
function made up of one or more outer stops interpreted as a camera function
with a single inner stop at each zoom level that is interpreted as a source
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;

#pragma mark Initializing a Composite Function

/**
Returns an `MGLCompositeStyleFunction` object representing a composite
function made up of one or more outer stops interpreted as a camera function
with a single inner stop at each zoom level that is interpreted as a source
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)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;

// 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. The nested dictionary key is an object representing a feature
attribute key. The nested dictionary value is an `MGLStyleValue` object
containing the value to use when the function is given the associated attribute
key at the outer zoom level. 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
Loading