[ios, macos] Add text-color support to format expressions. (#14146)
Added the possibility of overriding paint properties inside the format expression. Added an example of how to create an MGLAttributedExpression object and documented the attributes keys and value types. Fixed a bug that ignored the font names.
This commit is contained in:
committed by
GitHub
parent
10e1e63aee
commit
174c8fa7e4
@@ -431,5 +431,16 @@ In style JSON | In the format string
|
||||
`["any", f0, …, fn]` | `p0 OR … OR pn`
|
||||
`["none", f0, …, fn]` | `NOT (p0 OR … OR pn)`
|
||||
|
||||
## Specifying the text format
|
||||
|
||||
The following format attributes are defined as `NSString` constans that you
|
||||
can use to update the formatting of `MGLSymbolStyleLayer.text` property.
|
||||
|
||||
In style JSON | In Objective-C | In Swift
|
||||
--------------|-----------------------|---------
|
||||
`text-font` | `MGLFontNamesAttribute` | `.fontNamesAttribute`
|
||||
`font-scale` | `MGLFontSizeAttribute` | `.fontSizeAttribute`
|
||||
`text-color` | `MGLFontColorAttribute` | `.fontColorAttribute`
|
||||
|
||||
See the “[Predicates and Expressions](predicates-and-expressions.html)” guide for
|
||||
a full description of the supported operators and operand types.
|
||||
|
||||
@@ -546,6 +546,14 @@ operator in the Mapbox Style Specification.
|
||||
Concatenates and returns the array of `MGLAttributedExpression` objects, for use
|
||||
with the `MGLSymbolStyleLayer.text` property.
|
||||
|
||||
`MGLAttributedExpression.attributes` valid attributes.
|
||||
|
||||
Key | Value Type
|
||||
--- | ---
|
||||
`MGLFontNamesAttribute` | `NSArray<NSString *>*`
|
||||
`MGLFontSizeAttribute` | `NSNumber`
|
||||
`MGLFontColorAttribute` | `UIColor` or `NSColor` on macos
|
||||
|
||||
This function corresponds to the
|
||||
[`format`](https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-format)
|
||||
operator in the Mapbox Style Specification.
|
||||
|
||||
@@ -6,10 +6,23 @@ typedef NSString * MGLAttributedExpressionKey NS_EXTENSIBLE_STRING_ENUM;
|
||||
|
||||
FOUNDATION_EXTERN MGL_EXPORT MGLAttributedExpressionKey const MGLFontNamesAttribute;
|
||||
FOUNDATION_EXTERN MGL_EXPORT MGLAttributedExpressionKey const MGLFontSizeAttribute;
|
||||
FOUNDATION_EXTERN MGL_EXPORT MGLAttributedExpressionKey const MGLFontColorAttribute;
|
||||
|
||||
/**
|
||||
An `MGLAttributedExpression` object associates text formatting attibutes (such as font size or
|
||||
font names) to an `NSExpression`.
|
||||
|
||||
### Example
|
||||
```swift
|
||||
let redColor = UIColor.red
|
||||
let expression = NSExpression(forConstantValue: "Foo")
|
||||
let attributes: Dictionary<MGLAttributedExpressionKey, Any> = [.fontNamesAttribute : ["DIN Offc Pro Italic",
|
||||
"Arial Unicode MS Regular"],
|
||||
.fontSizeAttribute: 1.2,
|
||||
.fontColorAttribute: redColor]
|
||||
let attributedExpression = MGLAttributedExpression(expression, attributes:attributes)
|
||||
```
|
||||
|
||||
*/
|
||||
MGL_EXPORT
|
||||
@interface MGLAttributedExpression : NSObject
|
||||
@@ -19,10 +32,29 @@ MGL_EXPORT
|
||||
*/
|
||||
@property (strong, nonatomic) NSExpression *expression;
|
||||
|
||||
#if TARGET_OS_IPHONE
|
||||
/**
|
||||
The formatting attributes.
|
||||
The formatting attributes dictionary.
|
||||
Key | Value Type
|
||||
--- | ---
|
||||
`MGLFontNamesAttribute` | `NSArray<NSString *>*`
|
||||
`MGLFontSizeAttribute` | `NSNumber`
|
||||
`MGLFontColorAttribute` | `UIColor`
|
||||
|
||||
*/
|
||||
@property (strong, nonatomic, readonly) NSDictionary<MGLAttributedExpressionKey, id> *attributes;
|
||||
#else
|
||||
/**
|
||||
The formatting attributes dictionary.
|
||||
Key | Value Type
|
||||
--- | ---
|
||||
`MGLFontNamesAttribute` | `NSArray<NSString *>*`
|
||||
`MGLFontSizeAttribute` | `NSNumber`
|
||||
`MGLFontColorAttribute` | `NSColor`
|
||||
*/
|
||||
@property (strong, nonatomic, readonly) NSDictionary<MGLAttributedExpressionKey, id> *attributes;
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
Returns an `MGLAttributedExpression` object initialized with an expression and no attribute information.
|
||||
@@ -32,13 +64,18 @@ MGL_EXPORT
|
||||
/**
|
||||
Returns an `MGLAttributedExpression` object initialized with an expression and text format attributes.
|
||||
*/
|
||||
- (instancetype)initWithExpression:(NSExpression *)expression attributes:(nullable NSDictionary <MGLAttributedExpressionKey, id> *)attrs;
|
||||
- (instancetype)initWithExpression:(NSExpression *)expression attributes:(nonnull NSDictionary <MGLAttributedExpressionKey, id> *)attrs;
|
||||
|
||||
/**
|
||||
Creates an `MGLAttributedExpression` object initialized with an expression and the format attributes for font names and font size.
|
||||
*/
|
||||
+ (instancetype)attributedExpression:(NSExpression *)expression fontNames:(nullable NSArray<NSString*> *)fontNames fontSize:(nullable NSNumber *)fontSize;
|
||||
|
||||
/**
|
||||
Creates an `MGLAttributedExpression` object initialized with an expression and the format attributes dictionary.
|
||||
*/
|
||||
+ (instancetype)attributedExpression:(NSExpression *)expression attributes:(nonnull NSDictionary <MGLAttributedExpressionKey, id> *)attrs;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
|
||||
const MGLAttributedExpressionKey MGLFontNamesAttribute = @"text-font";
|
||||
const MGLAttributedExpressionKey MGLFontSizeAttribute = @"font-scale";
|
||||
const MGLAttributedExpressionKey MGLFontColorAttribute = @"text-color";
|
||||
|
||||
@implementation MGLAttributedExpression
|
||||
|
||||
- (instancetype)initWithExpression:(NSExpression *)expression {
|
||||
self = [self initWithExpression:expression attributes:nil];
|
||||
self = [self initWithExpression:expression attributes:@{}];
|
||||
return self;
|
||||
}
|
||||
|
||||
@@ -28,7 +29,15 @@ const MGLAttributedExpressionKey MGLFontSizeAttribute = @"font-scale";
|
||||
return attributedExpression;
|
||||
}
|
||||
|
||||
- (instancetype)initWithExpression:(NSExpression *)expression attributes:(NSDictionary<MGLAttributedExpressionKey,id> *)attrs {
|
||||
+ (instancetype)attributedExpression:(NSExpression *)expression attributes:(nonnull NSDictionary<MGLAttributedExpressionKey,id> *)attrs {
|
||||
MGLAttributedExpression *attributedExpression;
|
||||
|
||||
attributedExpression = [[self alloc] initWithExpression:expression attributes:attrs];
|
||||
|
||||
return attributedExpression;
|
||||
}
|
||||
|
||||
- (instancetype)initWithExpression:(NSExpression *)expression attributes:(nonnull NSDictionary<MGLAttributedExpressionKey,id> *)attrs {
|
||||
if (self = [super init])
|
||||
{
|
||||
MGLLogInfo(@"Starting %@ initialization.", NSStringFromClass([self class]));
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#import "MGLFoundation_Private.h"
|
||||
#import "NSExpression+MGLPrivateAdditions.h"
|
||||
|
||||
#import "MGLTypes.h"
|
||||
@@ -878,9 +879,23 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
|
||||
NSExpression *expression = [NSExpression expressionWithMGLJSONObject:argumentObjects[index]];
|
||||
NSMutableDictionary *attrs = [NSMutableDictionary dictionary];
|
||||
if ((index + 1) < argumentObjects.count) {
|
||||
attrs = argumentObjects[index + 1];
|
||||
attrs = [NSMutableDictionary dictionaryWithDictionary:argumentObjects[index + 1]];
|
||||
}
|
||||
|
||||
if (attrs.count) {
|
||||
if (NSArray *fontNames = MGL_OBJC_DYNAMIC_CAST(attrs[MGLFontNamesAttribute], NSArray)) {
|
||||
attrs[MGLFontNamesAttribute] = fontNames[1];
|
||||
}
|
||||
if (NSArray *colorArray = MGL_OBJC_DYNAMIC_CAST(attrs[MGLFontColorAttribute], NSArray)) {
|
||||
if ([colorArray[0] isEqualToString:@"rgb"] || [colorArray[0] isEqualToString:@"rgba"]) {
|
||||
NSArray *colorArguments = [colorArray subarrayWithRange:NSMakeRange(1, colorArray.count - 1)];
|
||||
NSArray *subexpressions = MGLSubexpressionsWithJSONObjects(colorArguments);
|
||||
MGLColor *color = [NSExpression mgl_colorWithRGBComponents:subexpressions];
|
||||
|
||||
attrs[MGLFontColorAttribute] = color;
|
||||
}
|
||||
}
|
||||
}
|
||||
MGLAttributedExpression *attributedExpression = [[MGLAttributedExpression alloc] initWithExpression:expression attributes:attrs];
|
||||
|
||||
[attributedExpressions addObject:[NSExpression expressionForConstantValue:attributedExpression]];
|
||||
@@ -1008,7 +1023,15 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
|
||||
[attributes addObject:jsonObject];
|
||||
}
|
||||
if (attributedExpression.attributes) {
|
||||
[attributes addObject:attributedExpression.attributes];
|
||||
NSMutableDictionary *attributedDictionary = [NSMutableDictionary dictionaryWithDictionary:attributedExpression.attributes];
|
||||
if (attributedDictionary[MGLFontNamesAttribute]) {
|
||||
attributedDictionary[MGLFontNamesAttribute] = @[@"literal", attributedDictionary[MGLFontNamesAttribute]];
|
||||
}
|
||||
if (attributedDictionary[MGLFontColorAttribute] && [attributedDictionary[MGLFontColorAttribute] isKindOfClass:[MGLColor class]]) {
|
||||
MGLColor *color = attributedDictionary[MGLFontColorAttribute];
|
||||
attributedDictionary[MGLFontColorAttribute] = color.mgl_jsonExpressionObject;
|
||||
}
|
||||
[attributes addObject:attributedDictionary];
|
||||
} else {
|
||||
[attributes addObject:@{}];
|
||||
}
|
||||
|
||||
@@ -542,6 +542,24 @@ class MGLDocumentationExampleTests: XCTestCase, MGLMapViewDelegate {
|
||||
}
|
||||
}
|
||||
|
||||
func testMGLAttributedExpression() {
|
||||
//#-example-code
|
||||
#if os(macOS)
|
||||
let redColor = NSColor.red
|
||||
#else
|
||||
let redColor = UIColor.red
|
||||
#endif
|
||||
let expression = NSExpression(forConstantValue: "Foo")
|
||||
let attributes: Dictionary<MGLAttributedExpressionKey, Any> = [.fontNamesAttribute : ["DIN Offc Pro Italic",
|
||||
"Arial Unicode MS Regular"],
|
||||
.fontSizeAttribute: 1.2,
|
||||
.fontColorAttribute: redColor]
|
||||
let attributedExpression = MGLAttributedExpression(expression, attributes:attributes)
|
||||
//#-end-example-code
|
||||
|
||||
XCTAssertNotNil(attributedExpression)
|
||||
}
|
||||
|
||||
// For testMGLMapView().
|
||||
func myCustomFunction() {}
|
||||
}
|
||||
|
||||
@@ -1049,6 +1049,43 @@ using namespace std::string_literals;
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
|
||||
}
|
||||
{
|
||||
MGLAttributedExpression *attribute1 = [[MGLAttributedExpression alloc] initWithExpression:[NSExpression expressionForConstantValue:@"foo"]
|
||||
attributes:@{ MGLFontSizeAttribute: @(1.2),
|
||||
MGLFontColorAttribute: @"yellow"}] ;
|
||||
NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_attributed:(%@)", MGLConstantExpression(attribute1)];
|
||||
|
||||
NSExpression *compatibilityExpression = [NSExpression expressionForFunction:@"mgl_attributed:" arguments:@[MGLConstantExpression(attribute1)]];
|
||||
NSArray *jsonExpression = @[ @"format", @"foo", @{ @"font-scale": @1.2, @"text-color": @"yellow" } ];
|
||||
XCTAssertEqualObjects(compatibilityExpression.mgl_jsonExpressionObject, expression.mgl_jsonExpressionObject);
|
||||
XCTAssertEqualObjects(compatibilityExpression, expression);
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
|
||||
}
|
||||
{
|
||||
MGLAttributedExpression *attribute1 = [[MGLAttributedExpression alloc] initWithExpression:[NSExpression expressionForConstantValue:@"foo"]
|
||||
attributes:@{ MGLFontSizeAttribute: @(1.2),
|
||||
MGLFontColorAttribute: @"yellow",
|
||||
MGLFontNamesAttribute: @[ @"DIN Offc Pro Bold", @"Arial Unicode MS Bold" ]
|
||||
}] ;
|
||||
NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_attributed:(%@)", MGLConstantExpression(attribute1)];
|
||||
|
||||
NSArray *jsonExpression = @[ @"format", @"foo", @{ @"font-scale": @1.2, @"text-color": @"yellow" , @"text-font" : @[ @"literal", @[ @"DIN Offc Pro Bold", @"Arial Unicode MS Bold" ]]} ];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
|
||||
}
|
||||
{
|
||||
MGLAttributedExpression *attribute1 = [[MGLAttributedExpression alloc] initWithExpression:[NSExpression expressionForConstantValue:@"foo"]
|
||||
attributes:@{ MGLFontSizeAttribute: @(1.2),
|
||||
MGLFontColorAttribute: [MGLColor redColor],
|
||||
MGLFontNamesAttribute: @[ @"DIN Offc Pro Bold", @"Arial Unicode MS Bold" ]
|
||||
}] ;
|
||||
NSExpression *expression = [NSExpression expressionWithFormat:@"mgl_attributed:(%@)", MGLConstantExpression(attribute1)];
|
||||
|
||||
NSArray *jsonExpression = @[ @"format", @"foo", @{ @"font-scale": @1.2, @"text-color": @[@"rgb", @255, @0, @0] , @"text-font" : @[ @"literal", @[ @"DIN Offc Pro Bold", @"Arial Unicode MS Bold" ]]} ];
|
||||
XCTAssertEqualObjects(expression.mgl_jsonExpressionObject, jsonExpression);
|
||||
XCTAssertEqualObjects([NSExpression expressionWithMGLJSONObject:jsonExpression], expression);
|
||||
}
|
||||
{
|
||||
MGLAttributedExpression *attribute1 = [MGLAttributedExpression attributedExpression:[NSExpression expressionForConstantValue:@"foo"]
|
||||
fontNames:nil
|
||||
|
||||
@@ -418,5 +418,16 @@ In style JSON | In the format string
|
||||
`["any", f0, …, fn]` | `p0 OR … OR pn`
|
||||
`["none", f0, …, fn]` | `NOT (p0 OR … OR pn)`
|
||||
|
||||
## Specifying the text format
|
||||
|
||||
The following format attributes are defined as `NSString` constans that you
|
||||
can use to update the formatting of `MGLSymbolStyleLayer.text` property.
|
||||
|
||||
In style JSON | In Objective-C | In Swift
|
||||
--------------|-----------------------|---------
|
||||
`text-font` | `MGLFontNamesAttribute` | `.fontNamesAttribute`
|
||||
`font-scale` | `MGLFontSizeAttribute` | `.fontSizeAttribute`
|
||||
`text-color` | `MGLFontColorAttribute` | `.fontColorAttribute`
|
||||
|
||||
See the “[Predicates and Expressions](predicates-and-expressions.html)” guide for
|
||||
a full description of the supported operators and operand types.
|
||||
|
||||
@@ -17,5 +17,6 @@
|
||||
|
||||
+ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components;
|
||||
+ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components;
|
||||
+ (UIColor *)mgl_colorWithRGBComponents:(NSArray<NSExpression *> *)components;
|
||||
|
||||
@end
|
||||
|
||||
@@ -411,5 +411,16 @@ In style JSON | In the format string
|
||||
`["any", f0, …, fn]` | `p0 OR … OR pn`
|
||||
`["none", f0, …, fn]` | `NOT (p0 OR … OR pn)`
|
||||
|
||||
## Specifying the text format
|
||||
|
||||
The following format attributes are defined as `NSString` constans that you
|
||||
can use to update the formatting of `MGLSymbolStyleLayer.text` property.
|
||||
|
||||
In style JSON | In Objective-C | In Swift
|
||||
--------------|-----------------------|---------
|
||||
`text-font` | `MGLFontNamesAttribute` | `.fontNamesAttribute`
|
||||
`font-scale` | `MGLFontSizeAttribute` | `.fontSizeAttribute`
|
||||
`text-color` | `MGLFontColorAttribute` | `.fontColorAttribute`
|
||||
|
||||
See the “[Predicates and Expressions](predicates-and-expressions.html)” guide for
|
||||
a full description of the supported operators and operand types.
|
||||
|
||||
@@ -23,5 +23,6 @@
|
||||
|
||||
+ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components;
|
||||
+ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components;
|
||||
+ (NSColor *)mgl_colorWithRGBComponents:(NSArray<NSExpression *> *)componentExpressions;
|
||||
|
||||
@end
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
@implementation NSExpression (MGLColorAdditions)
|
||||
|
||||
+ (NSExpression *)mgl_expressionForRGBComponents:(NSArray<NSExpression *> *)components {
|
||||
if (NSColor *color = [self mgl_colorWithComponentExpressions:components]) {
|
||||
if (NSColor *color = [self mgl_colorWithRGBComponents:components]) {
|
||||
return [NSExpression expressionForConstantValue:color];
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
}
|
||||
|
||||
+ (NSExpression *)mgl_expressionForRGBAComponents:(NSArray<NSExpression *> *)components {
|
||||
if (NSColor *color = [self mgl_colorWithComponentExpressions:components]) {
|
||||
if (NSColor *color = [self mgl_colorWithRGBComponents:components]) {
|
||||
return [NSExpression expressionForConstantValue:color];
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
/**
|
||||
Returns a color object corresponding to the given component expressions.
|
||||
*/
|
||||
+ (NSColor *)mgl_colorWithComponentExpressions:(NSArray<NSExpression *> *)componentExpressions {
|
||||
+ (NSColor *)mgl_colorWithRGBComponents:(NSArray<NSExpression *> *)componentExpressions {
|
||||
// Map the component expressions to constant components. If any component is
|
||||
// a non-constant expression, the components cannot be converted into a
|
||||
// constant color value.
|
||||
|
||||
Reference in New Issue
Block a user