[ios, macos] Minimal darwin wrappers of 'format' expression

Add support for `MGL_FUNCTION('format', <text>, <options dictionary>)`
This commit is contained in:
Chris Loer
2018-09-19 15:20:03 -07:00
committed by Chris Loer
parent ce76bde13d
commit d0cd49f516
8 changed files with 67 additions and 14 deletions

View File

@@ -38,7 +38,8 @@ std::unique_ptr<Expression> boolean(std::unique_ptr<Expression>);
std::unique_ptr<Expression> toColor(std::unique_ptr<Expression>);
std::unique_ptr<Expression> toString(std::unique_ptr<Expression>);
std::unique_ptr<Expression> toFormatted(std::unique_ptr<Expression>);
std::unique_ptr<Expression> get(const char* value);
std::unique_ptr<Expression> get(std::unique_ptr<Expression>);
@@ -78,6 +79,9 @@ std::unique_ptr<Expression> interpolate(Interpolator interpolator,
double input3, std::unique_ptr<Expression> output3);
std::unique_ptr<Expression> concat(std::vector<std::unique_ptr<Expression>> inputs);
std::unique_ptr<Expression> format(const char* value);
std::unique_ptr<Expression> format(std::unique_ptr<Expression>);
} // namespace dsl
} // namespace expression

View File

@@ -103,6 +103,11 @@ global.objCTestValue = function (property, layerType, arraysAsStructs, indent) {
case 'number':
return '@"1"';
case 'formatted':
// Special 'string' case to handle constant expression text-field that automatically
// converts Formatted back to string.
return layerType === 'string' ?
`@"'${_.startCase(propertyName)}'"` :
`@"MGL_FUNCTION('format', '${_.startCase(propertyName)}', %@)", @{}`;
case 'string':
return `@"'${_.startCase(propertyName)}'"`;
case 'enum':
@@ -559,6 +564,7 @@ global.valueTransformerArguments = function (property) {
case 'number':
return ['float', objCType];
case 'formatted':
return ['mbgl::style::expression::Formatted', objCType];
case 'string':
return ['std::string', objCType];
case 'enum':
@@ -593,6 +599,7 @@ global.mbglType = function(property) {
case 'number':
return 'float';
case 'formatted':
return 'mbgl::style::expression::Formatted';
case 'string':
return 'std::string';
case 'enum': {

View File

@@ -125,8 +125,13 @@ namespace mbgl {
if (<%- objCName(property) %> && <%- objCName(property) %>.expressionType == NSConstantValueExpressionType) {
std::string string = ((NSString *)<%- objCName(property) %>.constantValue).UTF8String;
if (mbgl::style::conversion::hasTokens(string)) {
<% if (property.type === 'formatted') { -%>
self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbgl::style::PropertyValue<mbgl::style::expression::Formatted>(
mbgl::style::conversion::convertTokenStringToFormatExpression(string)));
<% } else { -%>
self.rawLayer->set<%- camelize(originalPropertyName(property)) %>(mbgl::style::PropertyValue<std::string>(
mbgl::style::conversion::convertTokenStringToExpression(string)));
<% } -%>
return;
}
}

View File

@@ -162,6 +162,11 @@ private: // Private utilities for converting from mgl to mbgl values
mbglValue = rawValue.UTF8String;
}
// Formatted
void getMBGLValue(NSString *rawValue, mbgl::style::expression::Formatted &mbglValue) {
mbglValue = mbgl::style::expression::Formatted(rawValue.UTF8String);
}
// Offsets
void getMBGLValue(id rawValue, std::array<float, 2> &mbglValue) {
if ([rawValue isKindOfClass:[NSValue class]]) {
@@ -250,6 +255,11 @@ private: // Private utilities for converting from mbgl to mgl values
return @(mbglStopValue.c_str());
}
// Formatted
static NSString *toMGLRawStyleValue(const mbgl::style::expression::Formatted &mbglStopValue) {
return @(mbglStopValue.toString().c_str());
}
// Offsets
static NSValue *toMGLRawStyleValue(const std::array<float, 2> &mbglStopValue) {
return [NSValue mgl_valueWithOffsetArray:mbglStopValue];

View File

@@ -601,12 +601,12 @@ namespace mbgl {
if (text && text.expressionType == NSConstantValueExpressionType) {
std::string string = ((NSString *)text.constantValue).UTF8String;
if (mbgl::style::conversion::hasTokens(string)) {
self.rawLayer->setTextField(mbgl::style::PropertyValue<std::string>(
mbgl::style::conversion::convertTokenStringToExpression(string)));
self.rawLayer->setTextField(mbgl::style::PropertyValue<mbgl::style::expression::Formatted>(
mbgl::style::conversion::convertTokenStringToFormatExpression(string)));
return;
}
}
auto mbglValue = MGLStyleValueTransformer<std::string, NSString *>().toPropertyValue<mbgl::style::PropertyValue<std::string>>(text, true);
auto mbglValue = MGLStyleValueTransformer<mbgl::style::expression::Formatted, NSString *>().toPropertyValue<mbgl::style::PropertyValue<mbgl::style::expression::Formatted>>(text, true);
self.rawLayer->setTextField(mbglValue);
}
@@ -617,7 +617,7 @@ namespace mbgl {
if (propertyValue.isUndefined()) {
propertyValue = self.rawLayer->getDefaultTextField();
}
return MGLStyleValueTransformer<std::string, NSString *>().toExpression(propertyValue);
return MGLStyleValueTransformer<mbgl::style::expression::Formatted, NSString *>().toExpression(propertyValue);
}
- (void)setTextField:(NSExpression *)textField {

View File

@@ -1111,6 +1111,11 @@ NSArray *MGLSubexpressionsWithJSONObjects(NSArray *objects) {
// Avoid wrapping collator options object in literal expression.
return @[@"collator", self.arguments[1].constantValue];
}
if (op.expressionType == NSConstantValueExpressionType
&& [op.constantValue isEqualToString:@"format"]) {
// Avoid wrapping format options object in literal expression.
return @[@"format", self.arguments[1].mgl_jsonExpressionObject, self.arguments[2].constantValue];
}
return self.arguments.mgl_jsonExpressionObject;
} else if (op == [MGLColor class] && [function isEqualToString:@"colorWithRed:green:blue:alpha:"]) {
NSArray *arguments = self.arguments.mgl_jsonExpressionObject;

View File

@@ -68,7 +68,11 @@
@"<%- originalPropertyName(property) %> should be unset initially.");
NSExpression *defaultExpression = layer.<%- objCName(property) %>;
<% if (property.type === 'formatted') { -%>
NSExpression *constantExpression = [NSExpression expressionWithFormat:<%- objCTestValue(property, 'string', true, 3) %>];
<% } else { -%>
NSExpression *constantExpression = [NSExpression expressionWithFormat:<%- objCTestValue(property, type, true, 3) %>];
<% } -%>
layer.<%- objCName(property) %> = constantExpression;
mbgl::style::PropertyValue<<%- mbglType(property) %>> propertyValue = { <%- mbglTestValue(property, type) %> };
XCTAssertEqual(rawLayer->get<%- camelize(originalPropertyName(property)) %>(), propertyValue,
@@ -83,7 +87,11 @@
{
using namespace mbgl::style::expression::dsl;
propertyValue = mbgl::style::PropertyExpression<<%- mbglType(property) %>>(
<% if (property.type === 'formatted') { -%>
step(zoom(), format(<%- mbglExpressionTestValue(property, type) %>), 18.0, format(<%- mbglExpressionTestValue(property, type) %>))
<% } else { -%>
step(zoom(), literal(<%- mbglExpressionTestValue(property, type) %>), 18.0, literal(<%- mbglExpressionTestValue(property, type) %>))
<% } -%>
);
}
@@ -160,13 +168,23 @@
{
using namespace mbgl::style::expression::dsl;
propertyValue = mbgl::style::PropertyExpression<<%- mbglType(property) %>>(
<% if (property.type === 'formatted') { -%>
format(toString(get(literal("token"))))
<% } else { -%>
toString(get(literal("token")))
<% } -%>
);
}
XCTAssertEqual(rawLayer->get<%- camelize(originalPropertyName(property)) %>(), propertyValue,
@"Setting <%- objCName(property) %> to a constant string with tokens should convert to an expression.");
XCTAssertEqualObjects(layer.<%- objCName(property) %>, [NSExpression expressionWithFormat:@"CAST(token, \"NSString\")"],
<% if (property.type === 'formatted') { -%>
NSExpression* tokenExpression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('format', CAST(token, 'NSString'), %@)", @{}];
<% } else { -%>
NSExpression* tokenExpression = [NSExpression expressionWithFormat:@"CAST(token, \"NSString\")"];
<% } -%>
XCTAssertEqualObjects(layer.<%- objCName(property) %>, tokenExpression,
@"Setting <%- objCName(property) %> to a constant string with tokens should convert to an expression.");
<% } -%>
}

View File

@@ -224,7 +224,9 @@
XCTAssertEqual(rawLayer->getIconImage(), propertyValue,
@"Setting iconImageName to a constant string with tokens should convert to an expression.");
XCTAssertEqualObjects(layer.iconImageName, [NSExpression expressionWithFormat:@"CAST(token, \"NSString\")"],
NSExpression* tokenExpression = [NSExpression expressionWithFormat:@"CAST(token, \"NSString\")"];
XCTAssertEqualObjects(layer.iconImageName, tokenExpression,
@"Setting iconImageName to a constant string with tokens should convert to an expression.");
}
@@ -1096,20 +1098,20 @@
NSExpression *constantExpression = [NSExpression expressionWithFormat:@"'Text Field'"];
layer.text = constantExpression;
mbgl::style::PropertyValue<std::string> propertyValue = { "Text Field" };
mbgl::style::PropertyValue<mbgl::style::expression::Formatted> propertyValue = { "Text Field" };
XCTAssertEqual(rawLayer->getTextField(), propertyValue,
@"Setting text to a constant value expression should update text-field.");
XCTAssertEqualObjects(layer.text, constantExpression,
@"text should round-trip constant value expressions.");
constantExpression = [NSExpression expressionWithFormat:@"'Text Field'"];
constantExpression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('format', 'Text Field', %@)", @{}];
NSExpression *functionExpression = [NSExpression expressionWithFormat:@"mgl_step:from:stops:($zoomLevel, %@, %@)", constantExpression, @{@18: constantExpression}];
layer.text = functionExpression;
{
using namespace mbgl::style::expression::dsl;
propertyValue = mbgl::style::PropertyExpression<std::string>(
step(zoom(), literal("Text Field"), 18.0, literal("Text Field"))
propertyValue = mbgl::style::PropertyExpression<mbgl::style::expression::Formatted>(
step(zoom(), format("Text Field"), 18.0, format("Text Field"))
);
}
@@ -1130,14 +1132,16 @@
{
using namespace mbgl::style::expression::dsl;
propertyValue = mbgl::style::PropertyExpression<std::string>(
toString(get(literal("token")))
propertyValue = mbgl::style::PropertyExpression<mbgl::style::expression::Formatted>(
format(toString(get(literal("token"))))
);
}
XCTAssertEqual(rawLayer->getTextField(), propertyValue,
@"Setting text to a constant string with tokens should convert to an expression.");
XCTAssertEqualObjects(layer.text, [NSExpression expressionWithFormat:@"CAST(token, \"NSString\")"],
NSExpression* tokenExpression = [NSExpression expressionWithFormat:@"MGL_FUNCTION('format', CAST(token, 'NSString'), %@)", @{}];
XCTAssertEqualObjects(layer.text, tokenExpression,
@"Setting text to a constant string with tokens should convert to an expression.");
}