diff --git a/platform/darwin/src/MGLBaseStyleLayer_Private.h b/platform/darwin/src/MGLBaseStyleLayer_Private.h index e3d43906a..0cbb076b3 100644 --- a/platform/darwin/src/MGLBaseStyleLayer_Private.h +++ b/platform/darwin/src/MGLBaseStyleLayer_Private.h @@ -1,5 +1,7 @@ #import "MGLBaseStyleLayer.h" +#import "NSPredicate+MGLAdditions.h" + @interface MGLBaseStyleLayer (MGLBaseStyleLayer_Private) - (void)update; diff --git a/platform/darwin/src/MGLCircleStyleLayer.h b/platform/darwin/src/MGLCircleStyleLayer.h index 7d2ef0584..e4430044a 100644 --- a/platform/darwin/src/MGLCircleStyleLayer.h +++ b/platform/darwin/src/MGLCircleStyleLayer.h @@ -18,6 +18,14 @@ typedef NS_ENUM(NSUInteger, MGLCircleStyleLayerCirclePitchScale) { @interface MGLCircleStyleLayer : MGLBaseStyleLayer +/** + A predicate that corresponds to the layer's filter. + + The predicate's left expression must be a string that identifies a feature + property, or one of the special keys. + */ +@property (nonatomic, nullable) NSPredicate *predicate; + #pragma mark - Accessing the Paint Attributes /** diff --git a/platform/darwin/src/MGLCircleStyleLayer.mm b/platform/darwin/src/MGLCircleStyleLayer.mm index 27be01505..6c038318c 100644 --- a/platform/darwin/src/MGLCircleStyleLayer.mm +++ b/platform/darwin/src/MGLCircleStyleLayer.mm @@ -29,6 +29,16 @@ return self; } +- (void)setPredicate:(NSPredicate *)predicate +{ + self.layer->setFilter(predicate.mgl_filter); +} + +- (NSPredicate *)predicate +{ + return [NSPredicate mgl_predicateWithFilter:self.layer->getFilter()]; +} + #pragma mark - Accessing the Paint Attributes - (void)setCircleRadius:(id )circleRadius { diff --git a/platform/darwin/src/MGLFeature.mm b/platform/darwin/src/MGLFeature.mm index 3bf1e6115..6d4f76a71 100644 --- a/platform/darwin/src/MGLFeature.mm +++ b/platform/darwin/src/MGLFeature.mm @@ -3,6 +3,7 @@ #import "MGLPointAnnotation.h" #import "MGLPolyline.h" #import "MGLPolygon.h" +#import "MGLValueEvaluator.h" #import "MGLMultiPoint_Private.h" @@ -113,51 +114,7 @@ @end -/** - Recursively transforms a C++ type into the corresponding Foundation type. - */ -class PropertyValueEvaluator { -public: - id operator()(const mbgl::NullValue &) const { - return [NSNull null]; - } - - id operator()(const bool &value) const { - return value ? @YES : @NO; - } - - id operator()(const uint64_t &value) const { - return @(value); - } - - id operator()(const int64_t &value) const { - return @(value); - } - - id operator()(const double &value) const { - return @(value); - } - - id operator()(const std::string &value) const { - return @(value.c_str()); - } - - id operator()(const std::vector &values) const { - NSMutableArray *objects = [NSMutableArray arrayWithCapacity:values.size()]; - for (const auto &v : values) { - [objects addObject:mbgl::Value::visit(v, *this)]; - } - return objects; - } - - id operator()(const std::unordered_map &items) const { - NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:items.size()]; - for (auto &item : items) { - attributes[@(item.first.c_str())] = mbgl::Value::visit(item.second, *this); - } - return attributes; - } -}; + /** Transforms an `mbgl::geometry::geometry` type into an instance of the @@ -253,14 +210,14 @@ NS_ARRAY_OF(MGLShape *) *MGLFeaturesFromMBGLFeatures(const std::vec NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:feature.properties.size()]; for (auto &pair : feature.properties) { auto &value = pair.second; - PropertyValueEvaluator evaluator; + ValueEvaluator evaluator; attributes[@(pair.first.c_str())] = mbgl::Value::visit(value, evaluator); } GeometryEvaluator evaluator; MGLShape *shape = mapbox::geometry::geometry::visit(feature.geometry, evaluator); if (feature.id) { - shape.identifier = mbgl::FeatureIdentifier::visit(*feature.id, PropertyValueEvaluator()); + shape.identifier = mbgl::FeatureIdentifier::visit(*feature.id, ValueEvaluator()); } shape.attributes = attributes; [shapes addObject:shape]; diff --git a/platform/darwin/src/MGLFillStyleLayer.h b/platform/darwin/src/MGLFillStyleLayer.h index c03e8ecae..2d51f071e 100644 --- a/platform/darwin/src/MGLFillStyleLayer.h +++ b/platform/darwin/src/MGLFillStyleLayer.h @@ -13,6 +13,14 @@ typedef NS_ENUM(NSUInteger, MGLFillStyleLayerFillTranslateAnchor) { @interface MGLFillStyleLayer : MGLBaseStyleLayer +/** + A predicate that corresponds to the layer's filter. + + The predicate's left expression must be a string that identifies a feature + property, or one of the special keys. + */ +@property (nonatomic, nullable) NSPredicate *predicate; + #pragma mark - Accessing the Paint Attributes /** diff --git a/platform/darwin/src/MGLFillStyleLayer.mm b/platform/darwin/src/MGLFillStyleLayer.mm index 192235f69..c54ddba42 100644 --- a/platform/darwin/src/MGLFillStyleLayer.mm +++ b/platform/darwin/src/MGLFillStyleLayer.mm @@ -29,6 +29,16 @@ return self; } +- (void)setPredicate:(NSPredicate *)predicate +{ + self.layer->setFilter(predicate.mgl_filter); +} + +- (NSPredicate *)predicate +{ + return [NSPredicate mgl_predicateWithFilter:self.layer->getFilter()]; +} + #pragma mark - Accessing the Paint Attributes - (void)setFillAntialias:(id )fillAntialias { diff --git a/platform/darwin/src/MGLLineStyleLayer.h b/platform/darwin/src/MGLLineStyleLayer.h index 435829c50..5c2a3afc2 100644 --- a/platform/darwin/src/MGLLineStyleLayer.h +++ b/platform/darwin/src/MGLLineStyleLayer.h @@ -25,6 +25,14 @@ typedef NS_ENUM(NSUInteger, MGLLineStyleLayerLineTranslateAnchor) { @interface MGLLineStyleLayer : MGLBaseStyleLayer +/** + A predicate that corresponds to the layer's filter. + + The predicate's left expression must be a string that identifies a feature + property, or one of the special keys. + */ +@property (nonatomic, nullable) NSPredicate *predicate; + #pragma mark - Accessing the Layout Attributes /** diff --git a/platform/darwin/src/MGLLineStyleLayer.mm b/platform/darwin/src/MGLLineStyleLayer.mm index ffb0d4e39..ce9ad75f8 100644 --- a/platform/darwin/src/MGLLineStyleLayer.mm +++ b/platform/darwin/src/MGLLineStyleLayer.mm @@ -29,6 +29,16 @@ return self; } +- (void)setPredicate:(NSPredicate *)predicate +{ + self.layer->setFilter(predicate.mgl_filter); +} + +- (NSPredicate *)predicate +{ + return [NSPredicate mgl_predicateWithFilter:self.layer->getFilter()]; +} + #pragma mark - Accessing the Layout Attributes - (void)setLineCap:(id )lineCap { diff --git a/platform/darwin/src/MGLStyleLayer.h.ejs b/platform/darwin/src/MGLStyleLayer.h.ejs index 2b36a3067..8acda024c 100644 --- a/platform/darwin/src/MGLStyleLayer.h.ejs +++ b/platform/darwin/src/MGLStyleLayer.h.ejs @@ -35,6 +35,16 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(type) %>StyleLayer<%- camelize(prope <% } -%> @interface MGL<%- camelize(type) %>StyleLayer : MGLBaseStyleLayer +<% if (type !== 'background' && type !== 'raster') { -%> +/** + A predicate that corresponds to the layer's filter. + + The predicate's left expression must be a string that identifies a feature + property, or one of the special keys. + */ +@property (nonatomic, nullable) NSPredicate *predicate; + +<% } -%> <% if (layoutProperties.length) { -%> #pragma mark - Accessing the Layout Attributes @@ -53,6 +63,7 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(type) %>StyleLayer<%- camelize(prope <% } -%> <% } -%> +<% if (paintProperties.length) { -%> #pragma mark - Accessing the Paint Attributes <% for (const property of paintProperties) { -%> @@ -68,6 +79,7 @@ typedef NS_ENUM(NSUInteger, MGL<%- camelize(type) %>StyleLayer<%- camelize(prope */ @property (nonatomic<% if (!property.required) { %>, null_resettable<% } %>) <%- propertyType(property, false, type) %> <%- camelizeWithLeadingLowercase(property.name) %>; +<% } -%> <% } -%> @end diff --git a/platform/darwin/src/MGLStyleLayer.mm.ejs b/platform/darwin/src/MGLStyleLayer.mm.ejs index c35d254ca..4e59c3c6c 100644 --- a/platform/darwin/src/MGLStyleLayer.mm.ejs +++ b/platform/darwin/src/MGLStyleLayer.mm.ejs @@ -34,6 +34,18 @@ return self; } +<% if (type !== 'background' && type !== 'raster') { -%> +- (void)setPredicate:(NSPredicate *)predicate +{ + self.layer->setFilter(predicate.mgl_filter); +} + +- (NSPredicate *)predicate +{ + return [NSPredicate mgl_predicateWithFilter:self.layer->getFilter()]; +} + +<% } -%> <% if (layoutProperties.length) { -%> #pragma mark - Accessing the Layout Attributes diff --git a/platform/darwin/src/MGLSymbolStyleLayer.h b/platform/darwin/src/MGLSymbolStyleLayer.h index ef88ff996..eacd158dd 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.h +++ b/platform/darwin/src/MGLSymbolStyleLayer.h @@ -69,6 +69,14 @@ typedef NS_ENUM(NSUInteger, MGLSymbolStyleLayerTextTranslateAnchor) { @interface MGLSymbolStyleLayer : MGLBaseStyleLayer +/** + A predicate that corresponds to the layer's filter. + + The predicate's left expression must be a string that identifies a feature + property, or one of the special keys. + */ +@property (nonatomic, nullable) NSPredicate *predicate; + #pragma mark - Accessing the Layout Attributes /** diff --git a/platform/darwin/src/MGLSymbolStyleLayer.mm b/platform/darwin/src/MGLSymbolStyleLayer.mm index 159e3c4d0..b0553ea42 100644 --- a/platform/darwin/src/MGLSymbolStyleLayer.mm +++ b/platform/darwin/src/MGLSymbolStyleLayer.mm @@ -29,6 +29,16 @@ return self; } +- (void)setPredicate:(NSPredicate *)predicate +{ + self.layer->setFilter(predicate.mgl_filter); +} + +- (NSPredicate *)predicate +{ + return [NSPredicate mgl_predicateWithFilter:self.layer->getFilter()]; +} + #pragma mark - Accessing the Layout Attributes - (void)setSymbolPlacement:(id )symbolPlacement { diff --git a/platform/darwin/src/MGLValueEvaluator.h b/platform/darwin/src/MGLValueEvaluator.h new file mode 100644 index 000000000..b53cdaa8d --- /dev/null +++ b/platform/darwin/src/MGLValueEvaluator.h @@ -0,0 +1,49 @@ +#import + +#import + +/** + Recursively transforms a C++ type into the corresponding Foundation type. + */ +class ValueEvaluator { +public: + id operator()(const mbgl::NullValue &) const { + return [NSNull null]; + } + + id operator()(const bool &value) const { + return value ? @YES : @NO; + } + + id operator()(const uint64_t &value) const { + return @(value); + } + + id operator()(const int64_t &value) const { + return @(value); + } + + id operator()(const double &value) const { + return @(value); + } + + id operator()(const std::string &value) const { + return @(value.c_str()); + } + + id operator()(const std::vector &values) const { + NSMutableArray *objects = [NSMutableArray arrayWithCapacity:values.size()]; + for (const auto &v : values) { + [objects addObject:mbgl::Value::visit(v, *this)]; + } + return objects; + } + + id operator()(const std::unordered_map &items) const { + NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:items.size()]; + for (auto &item : items) { + attributes[@(item.first.c_str())] = mbgl::Value::visit(item.second, *this); + } + return attributes; + } +}; diff --git a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.h b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.h new file mode 100644 index 000000000..2cd4dd157 --- /dev/null +++ b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.h @@ -0,0 +1,7 @@ +#import + +#include + +@interface NSComparisonPredicate (MGLAdditions) + +@end diff --git a/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm new file mode 100644 index 000000000..ced6a1ac4 --- /dev/null +++ b/platform/darwin/src/NSComparisonPredicate+MGLAdditions.mm @@ -0,0 +1,67 @@ +#import "NSComparisonPredicate+MGLAdditions.h" + +#import "NSPredicate+MGLAdditions.h" +#import "NSExpression+MGLAdditions.h" + +@implementation NSComparisonPredicate (MGLAdditions) + +- (mbgl::style::Filter)mgl_filter +{ + switch (self.predicateOperatorType) { + case NSEqualToPredicateOperatorType: { + auto filter = mbgl::style::EqualsFilter(); + filter.key = self.leftExpression.keyPath.UTF8String; + filter.value = self.rightExpression.mgl_filterValue; + return filter; + } + case NSNotEqualToPredicateOperatorType: { + auto filter = mbgl::style::NotEqualsFilter(); + filter.key = self.leftExpression.keyPath.UTF8String; + filter.value = self.rightExpression.mgl_filterValue; + return filter; + } + case NSGreaterThanPredicateOperatorType: { + auto filter = mbgl::style::GreaterThanFilter(); + filter.key = self.leftExpression.keyPath.UTF8String; + filter.value = self.rightExpression.mgl_filterValue; + return filter; + } + case NSGreaterThanOrEqualToPredicateOperatorType: { + auto filter = mbgl::style::GreaterThanEqualsFilter(); + filter.key = self.leftExpression.keyPath.UTF8String; + filter.value = self.rightExpression.mgl_filterValue; + return filter; + } + case NSLessThanPredicateOperatorType: { + auto filter = mbgl::style::LessThanFilter(); + filter.key = self.leftExpression.keyPath.UTF8String; + filter.value = self.rightExpression.mgl_filterValue; + return filter; + } + case NSLessThanOrEqualToPredicateOperatorType: { + auto filter = mbgl::style::LessThanEqualsFilter(); + filter.key = self.leftExpression.keyPath.UTF8String; + filter.value = self.rightExpression.mgl_filterValue; + return filter; + } + case NSInPredicateOperatorType: { + auto filter = mbgl::style::InFilter(); + filter.key = self.leftExpression.keyPath.UTF8String; + filter.values = self.rightExpression.mgl_filterValues; + return filter; + } + case NSMatchesPredicateOperatorType: + case NSLikePredicateOperatorType: + case NSBeginsWithPredicateOperatorType: + case NSEndsWithPredicateOperatorType: + case NSCustomSelectorPredicateOperatorType: + case NSContainsPredicateOperatorType: + case NSBetweenPredicateOperatorType: + [NSException raise:@"Unsupported operator type" + format:@"NSPredicateOperatorType:%lu is not supported.", (unsigned long)self.predicateOperatorType]; + } + + return {}; +} + +@end diff --git a/platform/darwin/src/NSCompoundPredicate+MGLAdditions.h b/platform/darwin/src/NSCompoundPredicate+MGLAdditions.h new file mode 100644 index 000000000..0f9909255 --- /dev/null +++ b/platform/darwin/src/NSCompoundPredicate+MGLAdditions.h @@ -0,0 +1,7 @@ +#import + +#include + +@interface NSCompoundPredicate (MGLAdditions) + +@end diff --git a/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm b/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm new file mode 100644 index 000000000..07114308c --- /dev/null +++ b/platform/darwin/src/NSCompoundPredicate+MGLAdditions.mm @@ -0,0 +1,56 @@ +#import "NSCompoundPredicate+MGLAdditions.h" + +#import "NSPredicate+MGLAdditions.h" +#import "NSExpression+MGLAdditions.h" + +@implementation NSCompoundPredicate (MGLAdditions) + +- (std::vector)mgl_subfilters +{ + std::vectorfilters; + for (NSPredicate *predicate in self.subpredicates) { + filters.push_back(predicate.mgl_filter); + } + return filters; +} + +- (mbgl::style::Filter)mgl_filter +{ + switch (self.compoundPredicateType) { + case NSNotPredicateType: { + + // Translate a nested NSComparisonPredicate with operator type NSInPredicateOperatorType into a flat mbgl::NotIn filter. + NSArray *comparisonPredicates = [self.subpredicates filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"class == %@", [NSComparisonPredicate class]]]; + NSArray *notInPredicates = [comparisonPredicates filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSComparisonPredicate *_Nonnull predicate, NSDictionary * _Nullable bindings) { + return predicate.predicateOperatorType == NSInPredicateOperatorType; + }]]; + + if (notInPredicates.count) { + auto filter = mbgl::style::NotInFilter(); + filter.key = notInPredicates.firstObject.leftExpression.keyPath.UTF8String; + filter.values = notInPredicates.firstObject.rightExpression.mgl_filterValues; + return filter; + } else { + auto filter = mbgl::style::NoneFilter(); + filter.filters = [self mgl_subfilters]; + return filter; + } + } + case NSAndPredicateType: { + auto filter = mbgl::style::AllFilter(); + filter.filters = [self mgl_subfilters]; + return filter; + } + case NSOrPredicateType: { + auto filter = mbgl::style::AnyFilter(); + filter.filters = [self mgl_subfilters]; + return filter; + } + } + + [NSException raise:@"Compound predicate type not handled" + format:@""]; + return {}; +} + +@end diff --git a/platform/darwin/src/NSExpression+MGLAdditions.h b/platform/darwin/src/NSExpression+MGLAdditions.h new file mode 100644 index 000000000..4e8c5ee07 --- /dev/null +++ b/platform/darwin/src/NSExpression+MGLAdditions.h @@ -0,0 +1,11 @@ +#import + +#include + +@interface NSExpression (MGLAdditions) + +- (mbgl::Value)mgl_filterValue; + +- (std::vector)mgl_filterValues; + +@end diff --git a/platform/darwin/src/NSExpression+MGLAdditions.mm b/platform/darwin/src/NSExpression+MGLAdditions.mm new file mode 100644 index 000000000..5f1a1e765 --- /dev/null +++ b/platform/darwin/src/NSExpression+MGLAdditions.mm @@ -0,0 +1,43 @@ +#import "NSExpression+MGLAdditions.h" + +@implementation NSExpression (MGLAdditions) + +- (std::vector)mgl_filterValues +{ + if ([self.constantValue isKindOfClass:NSArray.class]) { + NSArray *values = self.constantValue; + std::vectorconvertedValues; + for (id value in values) { + convertedValues.push_back([self mgl_convertedValueWithValue:value]); + } + return convertedValues; + } + [NSException raise:@"Values not handled" format:@""]; + return { }; +} + +- (mbgl::Value)mgl_filterValue +{ + return [self mgl_convertedValueWithValue:self.constantValue]; +} + +- (mbgl::Value)mgl_convertedValueWithValue:(id)value +{ + if ([value isKindOfClass:NSString.class]) { + return { std::string([(NSString *)value UTF8String]) }; + } else if ([value isKindOfClass:NSNumber.class]) { + NSNumber *number = (NSNumber *)value; + if((strcmp([number objCType], @encode(int))) == 0) { + return { number.intValue }; + } else if ((strcmp([number objCType], @encode(double))) == 0) { + return { number.doubleValue }; + } else if ((strcmp([number objCType], @encode(bool))) == 0) { + return { number.boolValue }; + } + } + [NSException raise:@"Value not handled" + format:@"Can’t convert %s:%@ to mbgl::Value", [value objCType], value]; + return { }; +} + +@end diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.h b/platform/darwin/src/NSPredicate+MGLAdditions.h new file mode 100644 index 000000000..fd774dd58 --- /dev/null +++ b/platform/darwin/src/NSPredicate+MGLAdditions.h @@ -0,0 +1,13 @@ +#import + +#import "NSExpression+MGLAdditions.h" +#include + +@interface NSPredicate (MGLAdditions) + +- (mbgl::style::Filter)mgl_filter; + ++ (instancetype)mgl_predicateWithFilter:(mbgl::style::Filter)filter; + +@end + diff --git a/platform/darwin/src/NSPredicate+MGLAdditions.mm b/platform/darwin/src/NSPredicate+MGLAdditions.mm new file mode 100644 index 000000000..9c3f9c888 --- /dev/null +++ b/platform/darwin/src/NSPredicate+MGLAdditions.mm @@ -0,0 +1,107 @@ +#import "NSPredicate+MGLAdditions.h" + +#import "MGLValueEvaluator.h" + +class FilterEvaluator { +public: + + NSArray* getPredicates(std::vector filters) { + NSMutableArray *predicates = [NSMutableArray arrayWithCapacity:filters.size()]; + for (auto filter : filters) { + [predicates addObject:mbgl::style::Filter::visit(filter, FilterEvaluator())]; + } + return predicates; + } + + NSArray* getValues(std::vector values) { + NSMutableArray *array = [NSMutableArray arrayWithCapacity:values.size()]; + for (auto value : values) { + [array addObject:mbgl::Value::visit(value, ValueEvaluator())]; + } + return array; + } + + NSPredicate* operator()(mbgl::style::NullFilter filter) { + return nil; + } + + NSPredicate* operator()(mbgl::style::EqualsFilter filter) { + return [NSPredicate predicateWithFormat:@"%K == %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())]; + } + + NSPredicate* operator()(mbgl::style::NotEqualsFilter filter) { + return [NSPredicate predicateWithFormat:@"%K != %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())]; + } + + NSPredicate* operator()(mbgl::style::GreaterThanFilter filter) { + return [NSPredicate predicateWithFormat:@"%K > %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())]; + } + + NSPredicate* operator()(mbgl::style::GreaterThanEqualsFilter filter) { + return [NSPredicate predicateWithFormat:@"%K >= %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())]; + } + + NSPredicate* operator()(mbgl::style::LessThanFilter filter) { + return [NSPredicate predicateWithFormat:@"%K < %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())]; + } + + NSPredicate* operator()(mbgl::style::LessThanEqualsFilter filter) { + return [NSPredicate predicateWithFormat:@"%K <= %@", @(filter.key.c_str()), mbgl::Value::visit(filter.value, ValueEvaluator())]; + } + + NSPredicate* operator()(mbgl::style::InFilter filter) { + return [NSPredicate predicateWithFormat:@"%K IN %@", @(filter.key.c_str()), getValues(filter.values)]; + } + + NSPredicate* operator()(mbgl::style::NotInFilter filter) { + return [NSPredicate predicateWithFormat:@"NOT %K IN %@", @(filter.key.c_str()), getValues(filter.values)]; + } + + NSPredicate* operator()(mbgl::style::AnyFilter filter) { + return [NSCompoundPredicate orPredicateWithSubpredicates:getPredicates(filter.filters)]; + } + + NSPredicate* operator()(mbgl::style::AllFilter filter) { + return [NSCompoundPredicate andPredicateWithSubpredicates:getPredicates(filter.filters)]; + } + + NSPredicate* operator()(mbgl::style::NoneFilter filter) { + NSArray *predicates = getPredicates(filter.filters); + if (predicates.count > 1) { + NSCompoundPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:predicates]; + return [NSCompoundPredicate notPredicateWithSubpredicate:predicate]; + } else { + return [NSCompoundPredicate notPredicateWithSubpredicate:predicates.firstObject]; + } + } + + NSPredicate* operator()(mbgl::style::HasFilter filter) { + [NSException raise:@"Unsupported filter type" + format:@"Cannot convert mbgl::style::HasFilter to NSPredicate"]; + return nil; + } + + NSPredicate* operator()(mbgl::style::NotHasFilter filter) { + [NSException raise:@"Unsupported filter type" + format:@"Cannot convert mbgl::style::NotHasFilter to NSPredicate"]; + return nil; + } + +}; + +@implementation NSPredicate (MGLAdditions) + +- (mbgl::style::Filter)mgl_filter +{ + [NSException raise:@"Not supported" + format:@"NSPredicate doesn't implement ’-mgl_filter’. Try with NSComparisonPredicate or NSCompoundPredicate instead."]; + return {}; +} + ++ (instancetype)mgl_predicateWithFilter:(mbgl::style::Filter)filter +{ + FilterEvaluator evaluator; + return mbgl::style::Filter::visit(filter, evaluator); +} + +@end diff --git a/platform/darwin/test/MGLFilterTests.mm b/platform/darwin/test/MGLFilterTests.mm new file mode 100644 index 000000000..04cb82fac --- /dev/null +++ b/platform/darwin/test/MGLFilterTests.mm @@ -0,0 +1,137 @@ +#import "MGLStyleLayerTests.h" + +#import "NSPredicate+MGLAdditions.h" +#import "MGLValueEvaluator.h" + +@interface MGLFilterTests : MGLStyleLayerTests { + MGLGeoJSONSource *source; + MGLLineStyleLayer *layer; +} +@end + +@implementation MGLFilterTests + +- (void)setUp +{ + [super setUp]; + NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"]; + NSURL *url = [NSURL fileURLWithPath:filePath]; + NSData *geoJSONData = [NSData dataWithContentsOfURL:url]; + source = [[MGLGeoJSONSource alloc] initWithSourceIdentifier:@"test-source" geoJSONData:geoJSONData]; + [self.mapView.style addSource:source]; + layer = [[MGLLineStyleLayer alloc] initWithLayerIdentifier:@"test-layer" sourceIdentifier:@"test-source"]; +} + +- (void)tearDown +{ + [self.mapView.style removeLayer:layer]; + [self.mapView.style removeSource:source]; +} + +- (NSArray *)predicates +{ + NSPredicate *equalPredicate = [NSPredicate predicateWithFormat:@"type == 'neighbourhood'"]; + NSPredicate *notEqualPredicate = [NSPredicate predicateWithFormat:@"type != 'park'"]; + NSPredicate *greaterThanPredicate = [NSPredicate predicateWithFormat:@"%K > %@", @"stroke-width", @2.1]; + NSPredicate *greaterThanOrEqualToPredicate = [NSPredicate predicateWithFormat:@"%K >= %@", @"stroke-width", @2.1]; + NSPredicate *lessThanOrEqualToPredicate = [NSPredicate predicateWithFormat:@"%K <= %@", @"stroke-width", @2.1]; + NSPredicate *lessThanPredicate = [NSPredicate predicateWithFormat:@"%K < %@", @"stroke-width", @2.1]; + NSPredicate *inPredicate = [NSPredicate predicateWithFormat:@"type IN %@", @[@"park", @"neighbourhood"]]; + NSPredicate *notInPredicate = [NSPredicate predicateWithFormat:@"NOT (type IN %@)", @[@"park", @"neighbourhood"]]; + NSPredicate *inNotInPredicate = [NSPredicate predicateWithFormat:@"type IN %@ AND NOT (type IN %@)", @[@"park"], @[@"neighbourhood", @"test"]]; + NSPredicate *typePredicate = [NSPredicate predicateWithFormat:@"%K == %@", @"$type", @"Feature"]; + NSPredicate *idPredicate = [NSPredicate predicateWithFormat:@"%K == %@", @"$id", @"1234123"]; + NSPredicate *specialCharsPredicate = [NSPredicate predicateWithFormat:@"%K == %@", @"ty-’pè", @"sŒm-ethįng"]; + return @[equalPredicate, + notEqualPredicate, + greaterThanPredicate, + greaterThanOrEqualToPredicate, + lessThanOrEqualToPredicate, + lessThanPredicate, + inPredicate, + notInPredicate, + inNotInPredicate, + typePredicate, + idPredicate, + specialCharsPredicate]; +} + +- (void)testAllPredicates +{ + for (NSPredicate *predicate in self.predicates) { + layer.predicate = predicate; + XCTAssertEqualObjects(layer.predicate, predicate); + } + [self.mapView.style addLayer:layer]; +} + +- (void)testIntermittentEncoding +{ + NSPredicate *specialCharsPredicate = [NSPredicate predicateWithFormat:@"%K == %@", @"ty-’pè", @"sŒm-ethįng"]; + layer.predicate = specialCharsPredicate; + + NSComparisonPredicate *getPredicate = (NSComparisonPredicate *)layer.predicate; + mbgl::style::EqualsFilter filter = layer.predicate.mgl_filter.get(); + + id objcKey = getPredicate.leftExpression.keyPath; + id cppKey = @(filter.key.c_str()); + id objcValue = mbgl::Value::visit(getPredicate.rightExpression.mgl_filterValue, ValueEvaluator()); + id cppValue = mbgl::Value::visit(filter.value, ValueEvaluator()); + + XCTAssertEqualObjects(objcKey, cppKey); + XCTAssertEqualObjects(objcValue, cppValue); + + [self.mapView.style addLayer:layer]; +} + +- (void)testNestedFilters +{ + NSPredicate *equalPredicate = [NSPredicate predicateWithFormat:@"type == 'neighbourhood'"]; + NSPredicate *notEqualPredicate = [NSPredicate predicateWithFormat:@"type != 'park'"]; + + NSPredicate *allPredicate = [NSCompoundPredicate andPredicateWithSubpredicates:@[equalPredicate, notEqualPredicate]]; + NSPredicate *anyPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:@[equalPredicate, notEqualPredicate]]; + + layer.predicate = allPredicate; + XCTAssertEqualObjects(layer.predicate, allPredicate); + layer.predicate = anyPredicate; + XCTAssertEqualObjects(layer.predicate, anyPredicate); + + [self.mapView.style addLayer:layer]; +} + +- (void)testAndPredicates +{ + NSPredicate *predicate = [NSCompoundPredicate andPredicateWithSubpredicates:self.predicates]; + layer.predicate = predicate; + XCTAssertEqualObjects(predicate, layer.predicate); + [self.mapView.style addLayer:layer]; +} + +- (void)testOrPredicates +{ + NSPredicate *predicate = [NSCompoundPredicate orPredicateWithSubpredicates:self.predicates]; + layer.predicate = predicate; + XCTAssertEqualObjects(predicate, layer.predicate); + [self.mapView.style addLayer:layer]; +} + +- (void)testNotAndPredicates +{ + NSPredicate *predicates = [NSCompoundPredicate andPredicateWithSubpredicates:self.predicates]; + NSCompoundPredicate *predicate = [NSCompoundPredicate notPredicateWithSubpredicate:predicates]; + layer.predicate = predicate; + XCTAssertEqualObjects(predicate, layer.predicate); + [self.mapView.style addLayer:layer]; +} + +- (void)testNotOrPredicates +{ + NSPredicate *predicates = [NSCompoundPredicate orPredicateWithSubpredicates:self.predicates]; + NSCompoundPredicate *predicate = [NSCompoundPredicate notPredicateWithSubpredicate:predicates]; + layer.predicate = predicate; + XCTAssertEqualObjects(predicate, layer.predicate); + [self.mapView.style addLayer:layer]; +} + +@end diff --git a/platform/ios/test/MGLStyleLayerTests.xib b/platform/darwin/test/MGLStyleLayerTests.xib similarity index 92% rename from platform/ios/test/MGLStyleLayerTests.xib rename to platform/darwin/test/MGLStyleLayerTests.xib index a09476832..23ad22e7e 100644 --- a/platform/ios/test/MGLStyleLayerTests.xib +++ b/platform/darwin/test/MGLStyleLayerTests.xib @@ -1,7 +1,7 @@ - - + + - + @@ -15,7 +15,7 @@ - + diff --git a/platform/darwin/test/amsterdam.geojson b/platform/darwin/test/amsterdam.geojson index a0e28a8e9..a690f8c8a 100644 --- a/platform/darwin/test/amsterdam.geojson +++ b/platform/darwin/test/amsterdam.geojson @@ -162,7 +162,7 @@ "fill": "#555555", "fill-opacity": 0.5, "name": "Jordaan", - "type": "neighborhood", + "type": "neighbourhood", "description": "The Jordan was originally a working-class neighbourhood, and has now become a more upscale neighborhood. It is home to many art galleries, particularly for modern art, and is also dotted with speciality shops and restaurants. Markets are held regularly at Noordermarkt, the Westerstraat and Lindengracht." }, "geometry": { @@ -214,7 +214,7 @@ "fill": "#555555", "fill-opacity": 0.5, "name": "Prinseneiland", - "type": "neighborhood", + "type": "neighbourhood", "description": "Between 1610 and 1615 Prinseneiland was built as an extension of the harbor. Until the end of the 19th century this was an area with many wharfs, little industries and warehouses, related to the shipping trades. After the second World war the desolated area was discovered by many artists, who established their homes and studios in the vacant buildings. During the second half of the 20th century the old warehouses were transformed into apartments one after another, and new apartments were built. Nevertheless a lot of the atmosphere of the glorious past is still present in the old buildings and wooden drawbridges." }, "geometry": { diff --git a/platform/ios/app/MBXViewController.m b/platform/ios/app/MBXViewController.m index 605d6b2da..bfe3f2238 100644 --- a/platform/ios/app/MBXViewController.m +++ b/platform/ios/app/MBXViewController.m @@ -79,6 +79,29 @@ static NSString * const MBXViewControllerAnnotationViewReuseIdentifer = @"MBXVie self.debugLoggingEnabled = [[NSUserDefaults standardUserDefaults] boolForKey:@"MGLMapboxMetricsDebugLoggingEnabled"]; } +- (void)mapViewDidFinishLoadingMap:(MGLMapView *)mapView +{ + [mapView setCenterCoordinate:CLLocationCoordinate2DMake(52.36, 4.86) zoomLevel:12 animated:NO]; + +#warning DEBUG CODE + + NSString *filePath = [[NSBundle bundleForClass:self.class] pathForResource:@"amsterdam" ofType:@"geojson"]; + NSURL *url = [NSURL fileURLWithPath:filePath]; + NSData *geoJSONData = [NSData dataWithContentsOfURL:url]; + MGLGeoJSONSource *source = [[MGLGeoJSONSource alloc] initWithSourceIdentifier:@"source" geoJSONData:geoJSONData]; + [self.mapView.style addSource:source]; + + MGLFillStyleLayer *parksLayer = [[MGLFillStyleLayer alloc] initWithLayerIdentifier:@"park-layer" sourceIdentifier:@"source"]; + parksLayer.fillColor = [UIColor redColor]; + parksLayer.predicate = [NSPredicate predicateWithFormat:@"name == 'Westerpark'"]; + [self.mapView.style addLayer:parksLayer]; + + MGLFillStyleLayer *singleParkLayer = [[MGLFillStyleLayer alloc] initWithLayerIdentifier:@"single-park-layer" sourceIdentifier:@"source"]; + singleParkLayer.fillColor = [UIColor greenColor]; + singleParkLayer.predicate = [NSPredicate predicateWithFormat:@"name == 'vondelpark'"]; + [self.mapView.style addLayer:singleParkLayer]; +} + - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; diff --git a/platform/ios/ios.xcodeproj/project.pbxproj b/platform/ios/ios.xcodeproj/project.pbxproj index d3fc36732..24e5c16d9 100644 --- a/platform/ios/ios.xcodeproj/project.pbxproj +++ b/platform/ios/ios.xcodeproj/project.pbxproj @@ -37,6 +37,18 @@ 350098DD1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 350098DA1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h */; settings = {ATTRIBUTES = (Public, ); }; }; 350098DE1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 350098DB1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm */; }; 350098DF1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 350098DB1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm */; }; + 3510FFEA1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3510FFE81D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.h */; }; + 3510FFEB1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3510FFE81D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.h */; }; + 3510FFEC1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3510FFE91D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm */; }; + 3510FFED1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3510FFE91D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm */; }; + 3510FFF01D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3510FFEE1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h */; }; + 3510FFF11D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3510FFEE1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h */; }; + 3510FFF21D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3510FFEF1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm */; }; + 3510FFF31D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3510FFEF1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm */; }; + 3510FFF91D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3510FFF71D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h */; }; + 3510FFFA1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3510FFF71D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h */; }; + 3510FFFB1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3510FFF81D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm */; }; + 3510FFFC1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 3510FFF81D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm */; }; 35136D391D42271A00C20EFD /* MGLBackgroundStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35136D381D42271A00C20EFD /* MGLBackgroundStyleLayer.mm */; }; 35136D3A1D42271A00C20EFD /* MGLBackgroundStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35136D381D42271A00C20EFD /* MGLBackgroundStyleLayer.mm */; }; 35136D3C1D42272500C20EFD /* MGLCircleStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35136D3B1D42272500C20EFD /* MGLCircleStyleLayer.mm */; }; @@ -116,6 +128,11 @@ 3593E5261D529EDC006D9365 /* UIColor+MGLStyleAttributeAdditions_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 3593E5251D529EDC006D9365 /* UIColor+MGLStyleAttributeAdditions_Private.h */; }; 3593E5271D529EDC006D9365 /* UIColor+MGLStyleAttributeAdditions_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 3593E5251D529EDC006D9365 /* UIColor+MGLStyleAttributeAdditions_Private.h */; }; 359F57461D2FDDA6005217F1 /* MGLUserLocationAnnotationView_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 359F57451D2FDBD5005217F1 /* MGLUserLocationAnnotationView_Private.h */; }; + 35B82BF81D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35B82BF61D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h */; }; + 35B82BF91D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35B82BF61D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h */; }; + 35B82BFA1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35B82BF71D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm */; }; + 35B82BFB1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35B82BF71D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm */; }; + 35B8E08C1D6C8B5100E768D2 /* MGLFilterTests.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35B8E08B1D6C8B5100E768D2 /* MGLFilterTests.mm */; }; 35CE61821D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35CE61801D4165D9004F2359 /* UIColor+MGLAdditions.h */; }; 35CE61831D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 35CE61801D4165D9004F2359 /* UIColor+MGLAdditions.h */; }; 35CE61841D4165D9004F2359 /* UIColor+MGLAdditions.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35CE61811D4165D9004F2359 /* UIColor+MGLAdditions.mm */; }; @@ -130,6 +147,8 @@ 35D13AC61D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 35D13AC21D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm */; }; 35E0CFE61D3E501500188327 /* MGLStyle_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E0CFE51D3E501500188327 /* MGLStyle_Private.h */; }; 35E0CFE71D3E501500188327 /* MGLStyle_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E0CFE51D3E501500188327 /* MGLStyle_Private.h */; }; + 35E1A4D81D74336F007AA97F /* MGLValueEvaluator.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E1A4D71D74336F007AA97F /* MGLValueEvaluator.h */; }; + 35E1A4D91D74336F007AA97F /* MGLValueEvaluator.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E1A4D71D74336F007AA97F /* MGLValueEvaluator.h */; }; 35E208A71D24210F00EC9A46 /* MGLNSDataAdditionsTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 35E208A61D24210F00EC9A46 /* MGLNSDataAdditionsTests.m */; }; 35E79F201D41266300957B9E /* MGLStyleLayer_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E79F1F1D41266300957B9E /* MGLStyleLayer_Private.h */; }; 35E79F211D41266300957B9E /* MGLStyleLayer_Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 35E79F1F1D41266300957B9E /* MGLStyleLayer_Private.h */; }; @@ -474,6 +493,12 @@ 350098D71D4830D5004B2AF0 /* NSString+MGLStyleAttributeAdditions_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+MGLStyleAttributeAdditions_Private.h"; sourceTree = ""; }; 350098DA1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSValue+MGLStyleAttributeAdditions.h"; sourceTree = ""; }; 350098DB1D484E60004B2AF0 /* NSValue+MGLStyleAttributeAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSValue+MGLStyleAttributeAdditions.mm"; sourceTree = ""; }; + 3510FFE81D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSComparisonPredicate+MGLAdditions.h"; sourceTree = ""; }; + 3510FFE91D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSComparisonPredicate+MGLAdditions.mm"; sourceTree = ""; }; + 3510FFEE1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSExpression+MGLAdditions.h"; sourceTree = ""; }; + 3510FFEF1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSExpression+MGLAdditions.mm"; sourceTree = ""; }; + 3510FFF71D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSCompoundPredicate+MGLAdditions.h"; sourceTree = ""; }; + 3510FFF81D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSCompoundPredicate+MGLAdditions.mm"; sourceTree = ""; }; 35136D381D42271A00C20EFD /* MGLBackgroundStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLBackgroundStyleLayer.mm; sourceTree = ""; }; 35136D3B1D42272500C20EFD /* MGLCircleStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLCircleStyleLayer.mm; sourceTree = ""; }; 35136D3E1D42273000C20EFD /* MGLLineStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLLineStyleLayer.mm; sourceTree = ""; }; @@ -521,6 +546,9 @@ 3593E5201D529C29006D9365 /* MGLStyleAttribute.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLStyleAttribute.mm; sourceTree = ""; }; 3593E5251D529EDC006D9365 /* UIColor+MGLStyleAttributeAdditions_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+MGLStyleAttributeAdditions_Private.h"; sourceTree = ""; }; 359F57451D2FDBD5005217F1 /* MGLUserLocationAnnotationView_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MGLUserLocationAnnotationView_Private.h; sourceTree = ""; }; + 35B82BF61D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSPredicate+MGLAdditions.h"; sourceTree = ""; }; + 35B82BF71D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "NSPredicate+MGLAdditions.mm"; sourceTree = ""; }; + 35B8E08B1D6C8B5100E768D2 /* MGLFilterTests.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = MGLFilterTests.mm; path = ../../darwin/test/MGLFilterTests.mm; sourceTree = ""; }; 35CE61801D4165D9004F2359 /* UIColor+MGLAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+MGLAdditions.h"; sourceTree = ""; }; 35CE61811D4165D9004F2359 /* UIColor+MGLAdditions.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = "UIColor+MGLAdditions.mm"; sourceTree = ""; }; 35D13AB51D3D15E300AFB4E0 /* MGLStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyleLayer.h; sourceTree = ""; }; @@ -528,6 +556,7 @@ 35D13AC11D3D19DD00AFB4E0 /* MGLFillStyleLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLFillStyleLayer.h; sourceTree = ""; }; 35D13AC21D3D19DD00AFB4E0 /* MGLFillStyleLayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MGLFillStyleLayer.mm; sourceTree = ""; }; 35E0CFE51D3E501500188327 /* MGLStyle_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyle_Private.h; sourceTree = ""; }; + 35E1A4D71D74336F007AA97F /* MGLValueEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLValueEvaluator.h; sourceTree = ""; }; 35E208A61D24210F00EC9A46 /* MGLNSDataAdditionsTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MGLNSDataAdditionsTests.m; sourceTree = ""; }; 35E79F1F1D41266300957B9E /* MGLStyleLayer_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MGLStyleLayer_Private.h; sourceTree = ""; }; 36F1153B1D46080700878E1A /* libmbgl-core.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmbgl-core.a"; path = "build/Debug-iphoneos/libmbgl-core.a"; sourceTree = ""; }; @@ -850,6 +879,7 @@ isa = PBXGroup; children = ( 3575798F1D513EF1000B822E /* Layers */, + 35B8E08B1D6C8B5100E768D2 /* MGLFilterTests.mm */, ); name = Styling; sourceTree = ""; @@ -1038,6 +1068,7 @@ DA8847EE1CBAFA5100AB86E3 /* MGLTypes.h */, DA8848111CBAFA6200AB86E3 /* MGLTypes.m */, DA8848911CBB049300AB86E3 /* reachability */, + 35E1A4D71D74336F007AA97F /* MGLValueEvaluator.h */, ); name = Foundation; path = ../darwin/src; @@ -1262,6 +1293,14 @@ DAED38621D62D0FC00D7640F /* NSURL+MGLAdditions.m */, DA35A2C71CCAAAD200E826B2 /* NSValue+MGLAdditions.h */, DA35A2C81CCAAAD200E826B2 /* NSValue+MGLAdditions.m */, + 35B82BF61D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h */, + 35B82BF71D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm */, + 3510FFE81D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.h */, + 3510FFE91D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm */, + 3510FFEE1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h */, + 3510FFEF1D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm */, + 3510FFF71D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h */, + 3510FFF81D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm */, ); name = Categories; sourceTree = ""; @@ -1324,6 +1363,7 @@ 3593E5211D529C29006D9365 /* MGLStyleAttribute.h in Headers */, 35599DEB1D46F14E0048254D /* MGLStyleAttributeFunction.h in Headers */, 4018B1C91CDC288A00F666AF /* MGLAnnotationView_Private.h in Headers */, + 35E1A4D81D74336F007AA97F /* MGLValueEvaluator.h in Headers */, DA88482C1CBAFA6200AB86E3 /* NSBundle+MGLAdditions.h in Headers */, 35D13AB71D3D15E300AFB4E0 /* MGLStyleLayer.h in Headers */, 354D42DC1D4919F900F400A1 /* NSValue+MGLStyleAttributeAdditions_Private.h in Headers */, @@ -1333,6 +1373,7 @@ 404326891D5B9B27007111BD /* MGLAnnotationContainerView_Private.h in Headers */, DA88483B1CBAFB8500AB86E3 /* MGLCalloutView.h in Headers */, 35E0CFE61D3E501500188327 /* MGLStyle_Private.h in Headers */, + 3510FFF01D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */, 353AFA141D65AB17005A69F4 /* NSDate+MGLAdditions.h in Headers */, DAB4F8301D63DD7600E27738 /* MGLBaseStyleLayer_Private.h in Headers */, 3593E5261D529EDC006D9365 /* UIColor+MGLStyleAttributeAdditions_Private.h in Headers */, @@ -1347,13 +1388,14 @@ DA8847F01CBAFA5100AB86E3 /* MGLAnnotation.h in Headers */, DA88483E1CBAFB8500AB86E3 /* MGLMapView+MGLCustomStyleLayerAdditions.h in Headers */, 4018B1CA1CDC288E00F666AF /* MGLAnnotationView.h in Headers */, - 35E79F201D41266300957B9E /* MGLStyleLayer_Private.h in Headers */, 350098C61D48288B004B2AF0 /* NSNumber+MGLStyleAttributeAdditions_Private.h in Headers */, + 35E79F201D41266300957B9E /* MGLStyleLayer_Private.h in Headers */, 353933FB1D3FB7C0003F57D7 /* MGLRasterStyleLayer.h in Headers */, DA8847EF1CBAFA5100AB86E3 /* MGLAccountManager.h in Headers */, DA8848511CBAFB9800AB86E3 /* MGLAPIClient.h in Headers */, DA35A2C91CCAAAD200E826B2 /* NSValue+MGLAdditions.h in Headers */, 350098CF1D482E10004B2AF0 /* NSArray+MGLStyleAttributeAdditions_Private.h in Headers */, + 3510FFEA1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.h in Headers */, DA8848571CBAFB9800AB86E3 /* MGLMapboxEvents.h in Headers */, DA8848311CBAFA6200AB86E3 /* NSString+MGLAdditions.h in Headers */, 353933F81D3FB79F003F57D7 /* MGLLineStyleLayer.h in Headers */, @@ -1369,6 +1411,7 @@ DA88481E1CBAFA6200AB86E3 /* MGLMultiPoint_Private.h in Headers */, 3566C7661D4A77BA008152BC /* MGLGeoJSONSource.h in Headers */, 35CE61821D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */, + 35B82BF81D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h in Headers */, DA35A29E1CC9E94C00E826B2 /* MGLCoordinateFormatter.h in Headers */, DA8847F71CBAFA5100AB86E3 /* MGLOverlay.h in Headers */, DA35A2B11CCA141D00E826B2 /* MGLCompassDirectionFormatter.h in Headers */, @@ -1395,6 +1438,7 @@ DA88481B1CBAFA6200AB86E3 /* MGLGeometry_Private.h in Headers */, 350098CA1D482D9C004B2AF0 /* NSArray+MGLStyleAttributeAdditions.h in Headers */, 350098AF1D47E6F4004B2AF0 /* UIColor+MGLStyleAttributeAdditions.h in Headers */, + 3510FFF91D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h in Headers */, DA88485C1CBAFB9800AB86E3 /* MGLFaux3DUserLocationAnnotationView.h in Headers */, DA8848871CBB033F00AB86E3 /* Fabric.h in Headers */, 350098D81D4830D5004B2AF0 /* NSString+MGLStyleAttributeAdditions_Private.h in Headers */, @@ -1416,6 +1460,7 @@ isa = PBXHeadersBuildPhase; buildActionMask = 2147483647; files = ( + 35B82BF91D6C5F8400B1B721 /* NSPredicate+MGLAdditions.h in Headers */, DA35A2CA1CCAAAD200E826B2 /* NSValue+MGLAdditions.h in Headers */, 350098BC1D480108004B2AF0 /* MGLVectorSource.h in Headers */, 353933FC1D3FB7C0003F57D7 /* MGLRasterStyleLayer.h in Headers */, @@ -1431,6 +1476,7 @@ DA35A29F1CC9E94C00E826B2 /* MGLCoordinateFormatter.h in Headers */, DABFB8711CBE9A0F00D62B32 /* MGLMapView+MGLCustomStyleLayerAdditions.h in Headers */, DABFB8611CBE99E500D62B32 /* MGLMultiPoint.h in Headers */, + 3510FFF11D6D9D8C00F413B2 /* NSExpression+MGLAdditions.h in Headers */, 35E0CFE71D3E501500188327 /* MGLStyle_Private.h in Headers */, DAB4F8311D63DD7600E27738 /* MGLBaseStyleLayer_Private.h in Headers */, DABFB86D1CBE9A0F00D62B32 /* MGLAnnotationImage.h in Headers */, @@ -1446,9 +1492,12 @@ 350098C21D48149E004B2AF0 /* NSNumber+MGLStyleAttributeAdditions.h in Headers */, DABFB8691CBE99E500D62B32 /* MGLShape.h in Headers */, 350098CB1D482D9C004B2AF0 /* NSArray+MGLStyleAttributeAdditions.h in Headers */, + 3510FFEB1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.h in Headers */, + 35E1A4D91D74336F007AA97F /* MGLValueEvaluator.h in Headers */, DABFB8701CBE9A0F00D62B32 /* MGLMapView+IBAdditions.h in Headers */, 353AFA151D65AB17005A69F4 /* NSDate+MGLAdditions.h in Headers */, 350098D91D4830D5004B2AF0 /* NSString+MGLStyleAttributeAdditions_Private.h in Headers */, + 3510FFFA1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.h in Headers */, 35CE61831D4165D9004F2359 /* UIColor+MGLAdditions.h in Headers */, 350098B01D47E6F4004B2AF0 /* UIColor+MGLStyleAttributeAdditions.h in Headers */, DABFB8671CBE99E500D62B32 /* MGLPolygon.h in Headers */, @@ -1798,6 +1847,7 @@ 357579871D502AFE000B822E /* MGLLineStyleLayerTests.m in Sources */, 357579891D502B06000B822E /* MGLCircleStyleLayerTests.m in Sources */, DA35A2C51CCA9F8300E826B2 /* MGLClockDirectionFormatterTests.m in Sources */, + 35B8E08C1D6C8B5100E768D2 /* MGLFilterTests.mm in Sources */, 3575798B1D502B0C000B822E /* MGLBackgroundStyleLayerTests.m in Sources */, DA2E88621CC0382C00F24E7B /* MGLOfflinePackTests.m in Sources */, DA35A2AA1CCA058D00E826B2 /* MGLCoordinateFormatterTests.m in Sources */, @@ -1813,6 +1863,7 @@ buildActionMask = 2147483647; files = ( 35136D391D42271A00C20EFD /* MGLBackgroundStyleLayer.mm in Sources */, + 3510FFEC1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm in Sources */, 350098D51D4830A6004B2AF0 /* NSString+MGLStyleAttributeAdditions.mm in Sources */, 3593E5231D529C29006D9365 /* MGLStyleAttribute.mm in Sources */, 350098B11D47E6F4004B2AF0 /* UIColor+MGLStyleAttributeAdditions.mm in Sources */, @@ -1852,11 +1903,13 @@ 35305D481D22AA680007D005 /* NSData+MGLAdditions.mm in Sources */, DA8848291CBAFA6200AB86E3 /* MGLStyle.mm in Sources */, DA88481C1CBAFA6200AB86E3 /* MGLGeometry.mm in Sources */, + 3510FFF21D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm in Sources */, DA88481F1CBAFA6200AB86E3 /* MGLMultiPoint.mm in Sources */, DA88482B1CBAFA6200AB86E3 /* MGLTypes.m in Sources */, 4018B1C71CDC287F00F666AF /* MGLAnnotationView.mm in Sources */, DA88481D1CBAFA6200AB86E3 /* MGLMapCamera.mm in Sources */, DA8848261CBAFA6200AB86E3 /* MGLPolygon.mm in Sources */, + 35B82BFA1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */, DA8848521CBAFB9800AB86E3 /* MGLAPIClient.m in Sources */, DA8848301CBAFA6200AB86E3 /* NSProcessInfo+MGLAdditions.m in Sources */, 353AFA161D65AB17005A69F4 /* NSDate+MGLAdditions.mm in Sources */, @@ -1865,6 +1918,7 @@ DA88482A1CBAFA6200AB86E3 /* MGLTilePyramidOfflineRegion.mm in Sources */, 35136D3F1D42273000C20EFD /* MGLLineStyleLayer.mm in Sources */, DA88481A1CBAFA6200AB86E3 /* MGLAccountManager.m in Sources */, + 3510FFFB1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */, DA8848271CBAFA6200AB86E3 /* MGLPolyline.mm in Sources */, DA8848581CBAFB9800AB86E3 /* MGLMapboxEvents.m in Sources */, 35CE61841D4165D9004F2359 /* UIColor+MGLAdditions.mm in Sources */, @@ -1877,6 +1931,7 @@ buildActionMask = 2147483647; files = ( 35136D3A1D42271A00C20EFD /* MGLBackgroundStyleLayer.mm in Sources */, + 3510FFED1D6D9C7A00F413B2 /* NSComparisonPredicate+MGLAdditions.mm in Sources */, 350098D61D4830A6004B2AF0 /* NSString+MGLStyleAttributeAdditions.mm in Sources */, 354B83991D2E873E005D9406 /* MGLUserLocationAnnotationView.m in Sources */, DAA4E4221CBB730400178DFB /* MGLPointAnnotation.m in Sources */, @@ -1916,11 +1971,13 @@ DA35A2A21CC9E95F00E826B2 /* MGLCoordinateFormatter.m in Sources */, 35305D491D22AA680007D005 /* NSData+MGLAdditions.mm in Sources */, DAA4E42D1CBB730400178DFB /* MGLAnnotationImage.m in Sources */, + 3510FFF31D6D9D8C00F413B2 /* NSExpression+MGLAdditions.mm in Sources */, DAA4E4301CBB730400178DFB /* MGLLocationManager.m in Sources */, DAA4E4321CBB730400178DFB /* MGLMapView.mm in Sources */, DAA4E41E1CBB730400178DFB /* MGLMapCamera.mm in Sources */, 4018B1C81CDC287F00F666AF /* MGLAnnotationView.mm in Sources */, DAA4E4341CBB730400178DFB /* MGLFaux3DUserLocationAnnotationView.m in Sources */, + 35B82BFB1D6C5F8400B1B721 /* NSPredicate+MGLAdditions.mm in Sources */, DAA4E4311CBB730400178DFB /* MGLMapboxEvents.m in Sources */, DAA4E4231CBB730400178DFB /* MGLPolygon.mm in Sources */, 353AFA171D65AB17005A69F4 /* NSDate+MGLAdditions.mm in Sources */, @@ -1929,6 +1986,7 @@ DAA4E4211CBB730400178DFB /* MGLOfflineStorage.mm in Sources */, 35136D401D42273000C20EFD /* MGLLineStyleLayer.mm in Sources */, DAA4E42F1CBB730400178DFB /* MGLCompactCalloutView.m in Sources */, + 3510FFFC1D6DCC4700F413B2 /* NSCompoundPredicate+MGLAdditions.mm in Sources */, DAA4E4271CBB730400178DFB /* MGLTilePyramidOfflineRegion.mm in Sources */, DAA4E41C1CBB730400178DFB /* MGLAccountManager.m in Sources */, 35CE61851D4165D9004F2359 /* UIColor+MGLAdditions.mm in Sources */, diff --git a/platform/macos/app/MapDocument.m b/platform/macos/app/MapDocument.m index 3bb8f5872..8d24b35b6 100644 --- a/platform/macos/app/MapDocument.m +++ b/platform/macos/app/MapDocument.m @@ -508,7 +508,8 @@ NS_ARRAY_OF(id ) *MBXFlattenedShapes(NS_ARRAY_OF(id