[android] "format" expression support
This commit is contained in:
committed by
Łukasz Paczos
parent
78a1c30e80
commit
12b4969454
@@ -183,7 +183,7 @@ public class Expression {
|
||||
*/
|
||||
public static Expression literal(@NonNull Object object) {
|
||||
if (object.getClass().isArray()) {
|
||||
return literal(ExpressionArray.toObjectArray(object));
|
||||
return literal(toObjectArray(object));
|
||||
} else if (object instanceof Expression) {
|
||||
throw new RuntimeException("Can't convert an expression to a literal");
|
||||
}
|
||||
@@ -197,7 +197,7 @@ public class Expression {
|
||||
* @return the expression
|
||||
*/
|
||||
public static Expression literal(@NonNull Object[] array) {
|
||||
return new ExpressionArray(array);
|
||||
return new Expression("literal", new ExpressionLiteralArray(array));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2872,7 +2872,8 @@ public class Expression {
|
||||
*
|
||||
* @param expression the expression to evaluate
|
||||
* @return expression
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-is-supported-script">Style specification</a>
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-is-supported-script">Style
|
||||
* specification</a>
|
||||
*/
|
||||
public static Expression isSupportedScript(Expression expression) {
|
||||
return new Expression("is-supported-script", expression);
|
||||
@@ -2902,7 +2903,8 @@ public class Expression {
|
||||
*
|
||||
* @param string the string to evaluate
|
||||
* @return expression
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-is-supported-script">Style specification</a>
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-is-supported-script">Style
|
||||
* specification</a>
|
||||
*/
|
||||
public static Expression isSupportedScript(String string) {
|
||||
return new Expression("is-supported-script", literal(string));
|
||||
@@ -3224,9 +3226,121 @@ public class Expression {
|
||||
return new Expression("collator", new ExpressionMap(map));
|
||||
}
|
||||
|
||||
public static Expression format(Expression input) {
|
||||
Map<String, Expression> map = new HashMap<>();
|
||||
return new Expression("format", input, new ExpressionMap(map));
|
||||
/**
|
||||
* Returns formatted text containing annotations for use in mixed-format text-field entries.
|
||||
* <p>
|
||||
* To build the expression, use {@link #formatEntry(Expression, FormatOption...)}.
|
||||
* <p>
|
||||
* "format" expression can be used, for example, with the {@link PropertyFactory#textField(Expression)}
|
||||
* and accepts unlimited numbers of formatted sections.
|
||||
* <p>
|
||||
* Each section consist of the input, the displayed text, and options, like font-scale and text-font.
|
||||
* <p>
|
||||
* Example usage:
|
||||
* </p>
|
||||
* <pre>
|
||||
* {@code
|
||||
* SymbolLayer symbolLayer = new SymbolLayer("layer-id", "source-id");
|
||||
* symbolLayer.setProperties(
|
||||
* textField(
|
||||
* format(
|
||||
* formatEntry(
|
||||
* get("header_property"),
|
||||
* fontScale(2.0),
|
||||
* textFont(new String[] {"DIN Offc Pro Regular", "Arial Unicode MS Regular"})
|
||||
* ),
|
||||
* formatEntry(concat(literal("\n"), get("description_property")), fontScale(1.5)),
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param formatEntries format entries
|
||||
* @return expression
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#expressions-types-format">Style specification</a>
|
||||
*/
|
||||
public static Expression format(@NonNull FormatEntry... formatEntries) {
|
||||
// for each entry we are going to build an input and parameters
|
||||
Expression[] mappedExpressions = new Expression[formatEntries.length * 2];
|
||||
|
||||
int mappedIndex = 0;
|
||||
for (FormatEntry formatEntry : formatEntries) {
|
||||
// input
|
||||
mappedExpressions[mappedIndex++] = formatEntry.text;
|
||||
|
||||
// parameters
|
||||
Map<String, Expression> map = new HashMap<>();
|
||||
|
||||
if (formatEntry.options != null) {
|
||||
for (FormatOption option : formatEntry.options) {
|
||||
map.put(option.type, option.value);
|
||||
}
|
||||
}
|
||||
|
||||
mappedExpressions[mappedIndex++] = new ExpressionMap(map);
|
||||
}
|
||||
|
||||
return new Expression("format", mappedExpressions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a format entry that can be used in {@link #format(FormatEntry...)} to create formatted text fields.
|
||||
* <p>
|
||||
* Text is required to be of a resulting type string.
|
||||
* <p>
|
||||
* Text is required to be passed; {@link FormatOption}s are optional and will default to the base values defined
|
||||
* for the symbol.
|
||||
*
|
||||
* @param text displayed text
|
||||
* @param formatOptions format options
|
||||
* @return format entry
|
||||
*/
|
||||
public static FormatEntry formatEntry(@NonNull Expression text, @Nullable FormatOption... formatOptions) {
|
||||
return new FormatEntry(text, formatOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a format entry that can be used in {@link #format(FormatEntry...)} to create formatted text fields.
|
||||
* <p>
|
||||
* Text is required to be of a resulting type string.
|
||||
* <p>
|
||||
* Text is required to be passed; {@link FormatOption}s are optional and will default to the base values defined
|
||||
* for the symbol.
|
||||
*
|
||||
* @param text displayed text
|
||||
* @return format entry
|
||||
*/
|
||||
public static FormatEntry formatEntry(@NonNull Expression text) {
|
||||
return new FormatEntry(text, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a format entry that can be used in {@link #format(FormatEntry...)} to create formatted text fields.
|
||||
* <p>
|
||||
* Text is required to be of a resulting type string.
|
||||
* <p>
|
||||
* Text is required to be passed; {@link FormatOption}s are optional and will default to the base values defined
|
||||
* for the symbol.
|
||||
*
|
||||
* @param text displayed text
|
||||
* @param formatOptions format options
|
||||
* @return format entry
|
||||
*/
|
||||
public static FormatEntry formatEntry(@NonNull String text, @Nullable FormatOption... formatOptions) {
|
||||
return new FormatEntry(literal(text), formatOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a format entry that can be used in {@link #format(FormatEntry...)} to create formatted text fields.
|
||||
* <p>
|
||||
* Text is required to be of a resulting type string.
|
||||
* <p>
|
||||
* Text is required to be passed; {@link FormatOption}s are optional and will default to the base values defined
|
||||
* for the symbol.
|
||||
*
|
||||
* @param text displayed text
|
||||
* @return format entry
|
||||
*/
|
||||
public static FormatEntry formatEntry(@NonNull String text) {
|
||||
return new FormatEntry(literal(text), null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3981,18 +4095,7 @@ public class Expression {
|
||||
if (arguments != null) {
|
||||
for (Object argument : arguments) {
|
||||
builder.append(", ");
|
||||
if (argument instanceof ExpressionLiteral) {
|
||||
Object literalValue = ((ExpressionLiteral) argument).toValue();
|
||||
|
||||
// special case for handling unusual input like 'rgba(r, g, b, a)'
|
||||
if (literalValue instanceof String) {
|
||||
builder.append("\"").append(literalValue).append("\"");
|
||||
} else {
|
||||
builder.append(literalValue);
|
||||
}
|
||||
} else {
|
||||
builder.append(argument.toString());
|
||||
}
|
||||
builder.append(argument.toString());
|
||||
}
|
||||
}
|
||||
builder.append("]");
|
||||
@@ -4230,6 +4333,99 @@ public class Expression {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds format entries used in a {@link #format(FormatEntry...)} expression.
|
||||
*/
|
||||
public static class FormatEntry {
|
||||
@NonNull
|
||||
private Expression text;
|
||||
@Nullable
|
||||
private FormatOption[] options;
|
||||
|
||||
FormatEntry(@NonNull Expression text, @Nullable FormatOption[] options) {
|
||||
this.text = text;
|
||||
this.options = options;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds format options used in a {@link #formatEntry(Expression, FormatOption...)} that builds
|
||||
* a {@link #format(FormatEntry...)} expression.
|
||||
* <p>
|
||||
* If an option is not set, it defaults to the base value defined for the symbol.
|
||||
*/
|
||||
public static class FormatOption {
|
||||
@NonNull
|
||||
private String type;
|
||||
@NonNull
|
||||
private Expression value;
|
||||
|
||||
FormatOption(@NonNull String type, @NonNull Expression value) {
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* If set, the font-scale argument specifies a scaling factor relative to the text-size
|
||||
* specified in the root layout properties.
|
||||
* <p>
|
||||
* "font-scale" is required to be of a resulting type number.
|
||||
*
|
||||
* @param expression expression
|
||||
* @return format option
|
||||
*/
|
||||
@NonNull
|
||||
public static FormatOption fontScale(@NonNull Expression expression) {
|
||||
return new FormatOption("font-scale", expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* If set, the font-scale argument specifies a scaling factor relative to the text-size
|
||||
* specified in the root layout properties.
|
||||
* <p>
|
||||
* "font-scale" is required to be of a resulting type number.
|
||||
*
|
||||
* @param scale value
|
||||
* @return format option
|
||||
*/
|
||||
@NonNull
|
||||
public static FormatOption fontScale(double scale) {
|
||||
return new FormatOption("font-scale", literal(scale));
|
||||
}
|
||||
|
||||
/**
|
||||
* If set, the text-font argument overrides the font specified by the root layout properties.
|
||||
* <p>
|
||||
* "text-font" is required to a literal array.
|
||||
* <p>
|
||||
* The requested font stack has to be a part of the used style.
|
||||
* For more information see <a href="https://www.mapbox.com/help/define-font-stack/">the documentation</a>.
|
||||
*
|
||||
* @param expression expression
|
||||
* @return format option
|
||||
*/
|
||||
@NonNull
|
||||
public static FormatOption textFont(@NonNull Expression expression) {
|
||||
return new FormatOption("text-font", expression);
|
||||
}
|
||||
|
||||
/**
|
||||
* If set, the text-font argument overrides the font specified by the root layout properties.
|
||||
* <p>
|
||||
* "text-font" is required to a literal array.
|
||||
* <p>
|
||||
* The requested font stack has to be a part of the used style.
|
||||
* For more information see <a href="https://www.mapbox.com/help/define-font-stack/">the documentation</a>.
|
||||
*
|
||||
* @param fontStack value
|
||||
* @return format option
|
||||
*/
|
||||
@NonNull
|
||||
public static FormatOption textFont(@NonNull String[] fontStack) {
|
||||
return new FormatOption("text-font", literal(fontStack));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a JsonArray or a raw expression to a Java expression.
|
||||
*/
|
||||
@@ -4251,10 +4447,24 @@ public class Expression {
|
||||
final String operator = jsonArray.get(0).getAsString();
|
||||
final List<Expression> arguments = new ArrayList<>();
|
||||
|
||||
JsonElement jsonElement;
|
||||
for (int i = 1; i < jsonArray.size(); i++) {
|
||||
jsonElement = jsonArray.get(i);
|
||||
arguments.add(convert(jsonElement));
|
||||
JsonElement jsonElement = jsonArray.get(i);
|
||||
if (operator.equals("literal") && jsonElement instanceof JsonArray) {
|
||||
JsonArray nestedArray = (JsonArray) jsonElement;
|
||||
Object[] array = new Object[nestedArray.size()];
|
||||
for (int j = 0; j < nestedArray.size(); j++) {
|
||||
JsonElement element = nestedArray.get(j);
|
||||
if (element instanceof JsonPrimitive) {
|
||||
array[j] = convertToValue((JsonPrimitive) element);
|
||||
} else {
|
||||
throw new IllegalArgumentException("Nested literal arrays are not supported.");
|
||||
}
|
||||
}
|
||||
|
||||
arguments.add(new ExpressionLiteralArray(array));
|
||||
} else {
|
||||
arguments.add(convert(jsonElement));
|
||||
}
|
||||
}
|
||||
return new Expression(operator, arguments.toArray(new Expression[arguments.size()]));
|
||||
}
|
||||
@@ -4290,12 +4500,22 @@ public class Expression {
|
||||
* @return the expression literal
|
||||
*/
|
||||
private static Expression convert(@NonNull JsonPrimitive jsonPrimitive) {
|
||||
return new ExpressionLiteral(convertToValue(jsonPrimitive));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a JsonPrimitive to value
|
||||
*
|
||||
* @param jsonPrimitive the json primitive to convert
|
||||
* @return the value
|
||||
*/
|
||||
private static Object convertToValue(@NonNull JsonPrimitive jsonPrimitive) {
|
||||
if (jsonPrimitive.isBoolean()) {
|
||||
return new Expression.ExpressionLiteral(jsonPrimitive.getAsBoolean());
|
||||
return jsonPrimitive.getAsBoolean();
|
||||
} else if (jsonPrimitive.isNumber()) {
|
||||
return new Expression.ExpressionLiteral(jsonPrimitive.getAsFloat());
|
||||
return jsonPrimitive.getAsFloat();
|
||||
} else if (jsonPrimitive.isString()) {
|
||||
return new Expression.ExpressionLiteral(jsonPrimitive.getAsString());
|
||||
return jsonPrimitive.getAsString();
|
||||
} else {
|
||||
throw new RuntimeException("Unsupported literal expression conversion for " + jsonPrimitive.getClass());
|
||||
}
|
||||
@@ -4316,20 +4536,15 @@ public class Expression {
|
||||
/**
|
||||
* Expression to wrap Object[] as a literal
|
||||
*/
|
||||
private static class ExpressionArray extends Expression {
|
||||
private static class ExpressionLiteralArray extends ExpressionLiteral {
|
||||
|
||||
private Object[] array;
|
||||
|
||||
ExpressionArray(Object[] array) {
|
||||
this.array = array;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return new Object[] {
|
||||
"literal", array
|
||||
};
|
||||
/**
|
||||
* Create an expression literal.
|
||||
*
|
||||
* @param object the object to be treated as literal
|
||||
*/
|
||||
ExpressionLiteralArray(@NonNull Object[] object) {
|
||||
super(object);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4339,10 +4554,10 @@ public class Expression {
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder("[\"literal\"], [");
|
||||
Object argument;
|
||||
Object[] array = (Object[]) literal;
|
||||
StringBuilder builder = new StringBuilder("[");
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
argument = array[i];
|
||||
Object argument = array[i];
|
||||
if (argument instanceof String) {
|
||||
builder.append("\"").append(argument).append("\"");
|
||||
} else {
|
||||
@@ -4353,9 +4568,23 @@ public class Expression {
|
||||
builder.append(", ");
|
||||
}
|
||||
}
|
||||
builder.append("]]");
|
||||
builder.append("]");
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ExpressionLiteralArray that = (ExpressionLiteralArray) o;
|
||||
|
||||
return Arrays.equals((Object[]) this.literal, (Object[]) that.literal);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4373,8 +4602,8 @@ public class Expression {
|
||||
Map<String, Object> unwrappedMap = new HashMap<>();
|
||||
for (String key : map.keySet()) {
|
||||
Expression expression = map.get(key);
|
||||
if (expression instanceof Expression.ExpressionLiteral) {
|
||||
unwrappedMap.put(key, ((ExpressionLiteral) expression).toValue());
|
||||
if (expression instanceof ValueExpression) {
|
||||
unwrappedMap.put(key, ((ValueExpression) expression).toValue());
|
||||
} else {
|
||||
unwrappedMap.put(key, expression.toArray());
|
||||
}
|
||||
@@ -4437,7 +4666,7 @@ public class Expression {
|
||||
* @param object the object to convert to an object array
|
||||
* @return the converted object array
|
||||
*/
|
||||
static Object[] toObjectArray(Object object) {
|
||||
private static Object[] toObjectArray(Object object) {
|
||||
// object is a primitive array
|
||||
int len = java.lang.reflect.Array.getLength(object);
|
||||
Object[] objects = new Object[len];
|
||||
|
||||
@@ -62,7 +62,7 @@ public class PropertyValue<T> {
|
||||
? Expression.Converter.convert((JsonArray) value)
|
||||
: (Expression) value;
|
||||
} else {
|
||||
Logger.w(TAG, "not a expression, try value");
|
||||
Logger.w(TAG, "not an expression, try PropertyValue#getValue()");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ public class PropertyValue<T> {
|
||||
// noinspection unchecked
|
||||
return value;
|
||||
} else {
|
||||
Logger.w(TAG, "not a value, try function");
|
||||
Logger.w(TAG, "not a value, try PropertyValue#getExpression()");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.mapbox.mapboxsdk.style.expressions.Expression;
|
||||
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
|
||||
import com.mapbox.mapboxsdk.style.types.Formatted;
|
||||
import com.mapbox.mapboxsdk.style.types.FormattedSection;
|
||||
|
||||
/**
|
||||
* An icon or a text label.
|
||||
@@ -365,7 +367,31 @@ public class SymbolLayer extends Layer {
|
||||
@SuppressWarnings("unchecked")
|
||||
public PropertyValue<String> getTextField() {
|
||||
checkThread();
|
||||
return (PropertyValue<String>) new PropertyValue("text-field", nativeGetTextField());
|
||||
|
||||
PropertyValue propertyValue = new PropertyValue<>("text-field", nativeGetTextField());
|
||||
if (propertyValue.isExpression()) {
|
||||
return (PropertyValue<String>) propertyValue;
|
||||
} else {
|
||||
Formatted formatted = (Formatted) nativeGetTextField();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (FormattedSection section : formatted.getFormattedSections()) {
|
||||
builder.append(section.getText());
|
||||
}
|
||||
|
||||
return (PropertyValue<String>) new PropertyValue("text-field", builder.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the TextField property as {@link Formatted} object
|
||||
*
|
||||
* @return property wrapper value around String
|
||||
* @see Expression#format(Expression...)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public PropertyValue<Formatted> getFormattedTextField() {
|
||||
checkThread();
|
||||
return (PropertyValue<Formatted>) new PropertyValue("text-field", nativeGetTextField());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,6 +18,10 @@ import static com.mapbox.mapboxsdk.utils.ColorUtils.rgbaToColor;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.mapbox.mapboxsdk.style.expressions.Expression;
|
||||
import com.mapbox.mapboxsdk.style.layers.TransitionOptions;
|
||||
<% if (type === 'symbol') { -%>
|
||||
import com.mapbox.mapboxsdk.style.types.Formatted;
|
||||
import com.mapbox.mapboxsdk.style.types.FormattedSection;
|
||||
<% } -%>
|
||||
|
||||
/**
|
||||
* <%- doc %>
|
||||
@@ -171,8 +175,38 @@ public class <%- camelize(type) %>Layer extends Layer {
|
||||
@SuppressWarnings("unchecked")
|
||||
public PropertyValue<<%- propertyType(property) %>> get<%- camelize(property.name) %>() {
|
||||
checkThread();
|
||||
<% if (property.name === 'text-field' && property.type === 'formatted') { -%>
|
||||
|
||||
PropertyValue propertyValue = new PropertyValue<>("text-field", nativeGetTextField());
|
||||
if (propertyValue.isExpression()) {
|
||||
return (PropertyValue<String>) propertyValue;
|
||||
} else {
|
||||
Formatted formatted = (Formatted) nativeGetTextField();
|
||||
StringBuilder builder = new StringBuilder();
|
||||
for (FormattedSection section : formatted.getFormattedSections()) {
|
||||
builder.append(section.getText());
|
||||
}
|
||||
|
||||
return (PropertyValue<String>) new PropertyValue("text-field", builder.toString());
|
||||
}
|
||||
<% } else { -%>
|
||||
return (PropertyValue<<%- propertyType(property) %>>) new PropertyValue("<%- property.name %>", nativeGet<%- camelize(property.name) %>());
|
||||
<% } -%>
|
||||
}
|
||||
<% if (property.name === 'text-field' && property.type === 'formatted') { -%>
|
||||
|
||||
/**
|
||||
* Get the <%- camelize(property.name) %> property as {@link Formatted} object
|
||||
*
|
||||
* @return property wrapper value around <%- propertyType(property) %>
|
||||
* @see Expression#format(Expression...)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public PropertyValue<Formatted> getFormatted<%- camelize(property.name) %>() {
|
||||
checkThread();
|
||||
return (PropertyValue<Formatted>) new PropertyValue("<%- property.name %>", nativeGet<%- camelize(property.name) %>());
|
||||
}
|
||||
<% } -%>
|
||||
<% if (property.type == 'color') { -%>
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package com.mapbox.mapboxsdk.style.types;
|
||||
|
||||
import android.support.annotation.Keep;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Represents a string broken into sections annotated with separate formatting options.
|
||||
*
|
||||
* @see <a href="https://www.mapbox.com/mapbox-gl-js/style-spec/#types-formatted">Style specification</a>
|
||||
*/
|
||||
@Keep
|
||||
public class Formatted {
|
||||
private final FormattedSection[] formattedSections;
|
||||
|
||||
/**
|
||||
* Create a new formatted text.
|
||||
*
|
||||
* @param formattedSections sections with formatting options
|
||||
*/
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
|
||||
public Formatted(FormattedSection[] formattedSections) {
|
||||
this.formattedSections = formattedSections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns sections with separate formatting options that are a part of this formatted text.
|
||||
*
|
||||
* @return formatted sections
|
||||
*/
|
||||
public FormattedSection[] getFormattedSections() {
|
||||
return formattedSections;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Formatted formatted = (Formatted) o;
|
||||
|
||||
return Arrays.equals(formattedSections, formatted.formattedSections);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(formattedSections);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package com.mapbox.mapboxsdk.style.types;
|
||||
|
||||
import android.support.annotation.Keep;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.VisibleForTesting;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* A component of the {@link Formatted}.
|
||||
*/
|
||||
@Keep
|
||||
public class FormattedSection {
|
||||
private String text;
|
||||
private double fontScale;
|
||||
private String[] fontStack;
|
||||
|
||||
/**
|
||||
* Creates a formatted section.
|
||||
*
|
||||
* @param text displayed string
|
||||
* @param fontScale scale of the font, 1.0 is default
|
||||
* @param fontStack main and fallback fonts that are a part of the style
|
||||
*/
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
|
||||
public FormattedSection(@NonNull String text, double fontScale, @Nullable String[] fontStack) {
|
||||
this.text = text;
|
||||
this.fontScale = fontScale;
|
||||
this.fontStack = fontStack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a formatted section.
|
||||
*
|
||||
* @param text displayed string
|
||||
* @param fontScale scale of the font, 1.0 is default
|
||||
*/
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED)
|
||||
public FormattedSection(@NonNull String text, double fontScale) {
|
||||
this.text = text;
|
||||
this.fontScale = fontScale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the displayed text.
|
||||
*
|
||||
* @return text
|
||||
*/
|
||||
@NonNull
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns displayed text's font scale.
|
||||
*
|
||||
* @return font scale, defaults to 1.0
|
||||
*/
|
||||
public double getFontScale() {
|
||||
return fontScale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the font stack with main and fallback fonts.
|
||||
*
|
||||
* @return font stack
|
||||
*/
|
||||
@Nullable
|
||||
public String[] getFontStack() {
|
||||
return fontStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FormattedSection section = (FormattedSection) o;
|
||||
|
||||
return Double.compare(section.fontScale, fontScale) == 0
|
||||
&& (text != null ? text.equals(section.text) : section.text == null)
|
||||
&& Arrays.equals(fontStack, section.fontStack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result;
|
||||
long temp;
|
||||
result = text != null ? text.hashCode() : 0;
|
||||
temp = Double.doubleToLongBits(fontScale);
|
||||
result = 31 * result + (int) (temp ^ (temp >>> 32));
|
||||
result = 31 * result + Arrays.hashCode(fontStack);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user