diff options
author | Ivo van Dongen <info@ivovandongen.nl> | 2016-07-08 18:31:55 +0200 |
---|---|---|
committer | Ivo van Dongen <info@ivovandongen.nl> | 2016-07-26 16:29:26 -0400 |
commit | 9a3eadfd5baa8b070bf8d34fbd90ecae964f170c (patch) | |
tree | e8120b8f52821a9650ea2387d8eaf393404e0a0b /platform/android/scripts | |
parent | b3c914fb3f52f6a2b96d663f1c57c97c34eb5e23 (diff) | |
download | qtlocation-mapboxgl-9a3eadfd5baa8b070bf8d34fbd90ecae964f170c.tar.gz |
[android] #5610 - Initial Runtime Style Bindings
[android] #5610 - Adjusted public api after discussion
[android] #5610 - added jni binding for NativeMapView#getLayer
[android] #5610 - Added initial test Activity
[android] #5610 - Started on NativePeer implementation for Layer
[android] #5610 - replaced low-level jni code with high-level for native getLayer
[android] 5610 - completed basic layer peer class - constructible from java and c++
[android] #5610 - removed reference that was redundant and causing the finalizer exception
[android] #5610 - Added a property peer
[android] #5610 - added value type to do type conversions - wip
[android] #5610 - simplified property conversion approach - wrapped value with jenv
[android] #5610 - added some more value conversions
[android] #5610 - Finished conversion for basic types
[android] #5610 - allow color's to be set as either an android color int or a String to support all formats in the spec
[android] #5610 - encode color ints as rgba to retain alpha channel
[android] #5610 - recalculate classes after paint property
[android] #5610 - more examples
[android] #5610 - fixed the example
[android] #5610 - cleaned up example code before continueing
[android] #5610 - added layout property example
[android] #5610 - set visibility on layer
[android] #5610 - added removeLayer and example
[android] #5610 - added more type conversions
[android] #5610 - Started on peer classes for layer implementations - WIP
[android] #5610 - First complete layer subclass peer implementation
[android] #5610 - added a little bit of structure before adding the other layer types
[android] #5610 - generate the c++ headers from the style spec
[android] #5610 - make sure the visibility is set as a string
[android] #5610 - Generate c++ layer peer class implementations from the style spec
[android] #5610 - generate java layer peer classes
[android] #5610 - cleanup comments
[android] #5610 - register all c++ peer classes with jni
[android] #5610 - addLayer
[android] #5610 - comment out broken case
[android] #5610 - Sources api - very much WIP
[android] 5610 - GeoJson source implementation and geojson conversion
[android] #5610 - cleanup add source/layer example a bit
[android] #5610 - initial filter api
[android] #5610 - Added filter api on the relevant Layer classes
[android] #5610 - raster layer is not filterable
[android] #5610 - actually make it compile
[android] #5610 - completed filter implementation
[android] #5610 - Vector and Raster Source + examples
[android] #5610 - removed superfluous interface, moved filters to the correct package
[android] #5610 - fixed comments
[android] #5610 - moved tests to the right package
[android] #5610 - hide difference between paint and layout properties in public api, make more performant set method for proeprties
[android] #5610 - fix rebase issue
Diffstat (limited to 'platform/android/scripts')
-rw-r--r-- | platform/android/scripts/generate-style-code.js | 114 | ||||
-rw-r--r-- | platform/android/scripts/layer.cpp.ejs | 64 | ||||
-rw-r--r-- | platform/android/scripts/layer.hpp.ejs | 38 | ||||
-rw-r--r-- | platform/android/scripts/layer.java.ejs | 44 | ||||
-rw-r--r-- | platform/android/scripts/layer_property.java.ejs | 42 | ||||
-rw-r--r-- | platform/android/scripts/layer_property_factory.java.ejs | 45 |
6 files changed, 347 insertions, 0 deletions
diff --git a/platform/android/scripts/generate-style-code.js b/platform/android/scripts/generate-style-code.js new file mode 100644 index 0000000000..03bfac8067 --- /dev/null +++ b/platform/android/scripts/generate-style-code.js @@ -0,0 +1,114 @@ +'use strict'; + +const fs = require('fs'); +const ejs = require('ejs'); +const spec = require('mapbox-gl-style-spec').latest; +const _ = require('lodash'); + +global.iff = function (condition, val) { + return condition() ? val : ""; +} + + +global.camelize = function (str) { + return str.replace(/(?:^|-)(.)/g, function (_, x) { + return x.toUpperCase(); + }); +} + +global.camelizeWithLeadingLowercase = function (str) { + return str.replace(/-(.)/g, function (_, x) { + return x.toUpperCase(); + }); +} + +global.snakeCaseUpper = function (str) { + return str.replace(/-/g, "_").toUpperCase(); +} + +global.propertyType = function propertyType(property) { +//TODO: Doe we want these exceptions? +// if (/-translate-anchor$/.test(property.name)) { + // return 'TranslateAnchorType'; + // } + // if (/-(rotation|pitch)-alignment$/.test(property.name)) { + // return 'AlignmentType'; + // } + switch (property.type) { + case 'boolean': + return 'Boolean'; + case 'number': + return 'Float'; + case 'string': + return 'String'; + case 'enum': + return `String`; + case 'color': + return `String`; + case 'array': + return `${propertyType({type:property.value})}[]`; + default: + throw new Error(`unknown type for ${property.name}`); + } +} + +global.propertyTypeAnnotation = function propertyTypeAnnotation(property) { + switch (property.type) { + case 'enum': + return `@Property.${snakeCaseUpper(property.name)}`; + default: + return ""; + } +}; + +//Process Layers +const layers = spec.layer.type.values.map((type) => { + const layoutProperties = Object.keys(spec[`layout_${type}`]).reduce((memo, name) => { + if (name !== 'visibility') { + spec[`layout_${type}`][name].name = name; + memo.push(spec[`layout_${type}`][name]); + } + return memo; + }, []); + + const paintProperties = Object.keys(spec[`paint_${type}`]).reduce((memo, name) => { + spec[`paint_${type}`][name].name = name; + memo.push(spec[`paint_${type}`][name]); + return memo; + }, []); + + return { + type: type, + layoutProperties: layoutProperties, + paintProperties: paintProperties, + }; +}); + +const layerHpp = ejs.compile(fs.readFileSync('platform/android/scripts/layer.hpp.ejs', 'utf8'), {strict: true}); +const layerCpp = ejs.compile(fs.readFileSync('platform/android/scripts/layer.cpp.ejs', 'utf8'), {strict: true}); +const layerJava = ejs.compile(fs.readFileSync('platform/android/scripts/layer.java.ejs', 'utf8'), {strict: true}); + +for (const layer of layers) { + fs.writeFileSync(`platform/android/src/style/layers/${layer.type}_layer.hpp`, layerHpp(layer)); + fs.writeFileSync(`platform/android/src/style/layers/${layer.type}_layer.cpp`, layerCpp(layer)); + fs.writeFileSync(`platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/${camelize(layer.type)}Layer.java`, layerJava(layer)); +} + +//Process all layer properties +const layoutProperties = _(layers).map('layoutProperties').flatten().value(); +const paintProperties = _(layers).map('paintProperties').flatten().value(); + +const propertiesTemplate = ejs.compile(fs.readFileSync('platform/android/scripts/layer_property_factory.java.ejs', 'utf8'), {strict: true}); +fs.writeFileSync( + `platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/PropertyFactory.java`, + propertiesTemplate({layoutProperties: layoutProperties, paintProperties: paintProperties}) +); + +//Create types for the enum properties +const enumProperties = _(layoutProperties).union(paintProperties).filter({'type': 'enum'}).value(); +const enumPropertyTemplate = ejs.compile(fs.readFileSync('platform/android/scripts/layer_property.java.ejs', 'utf8'), {strict: true}); +fs.writeFileSync( + `platform/android/MapboxGLAndroidSDK/src/main/java/com/mapbox/mapboxsdk/style/layers/Property.java`, + enumPropertyTemplate({properties: enumProperties}) +); + diff --git a/platform/android/scripts/layer.cpp.ejs b/platform/android/scripts/layer.cpp.ejs new file mode 100644 index 0000000000..b53bc3c4d6 --- /dev/null +++ b/platform/android/scripts/layer.cpp.ejs @@ -0,0 +1,64 @@ +<% + const type = locals.type; +-%> +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. + +#include "<%- type %>_layer.hpp" + +#include <string> + +//XXX +#include <mbgl/platform/log.hpp> + +namespace mbgl { +namespace android { + +<% if (type === 'background') { -%> + <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(jni::JNIEnv& env, jni::String layerId) + : Layer(env, std::make_unique<mbgl::style::<%- camelize(type) %>Layer>(jni::Make<std::string>(env, layerId))) { +<% } else { -%> + <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId) + : Layer(env, std::make_unique<mbgl::style::<%- camelize(type) %>Layer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) { +<% } -%> + mbgl::Log::Debug(mbgl::Event::JNI, "<%- camelize(type) %>Layer constructed, owning reference"); + } + + <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(mbgl::Map& map, mbgl::style::<%- camelize(type) %>Layer& coreLayer) + : Layer(map, coreLayer) { + + mbgl::Log::Debug(mbgl::Event::JNI, "<%- camelize(type) %>Layer Non-owning reference constructor"); + } + + <%- camelize(type) %>Layer::~<%- camelize(type) %>Layer() = default; + + jni::Class<<%- camelize(type) %>Layer> <%- camelize(type) %>Layer::javaClass; + + jni::jobject* <%- camelize(type) %>Layer::createJavaPeer(jni::JNIEnv& env) { + static auto constructor = <%- camelize(type) %>Layer::javaClass.template GetConstructor<jni::jlong>(env); + return <%- camelize(type) %>Layer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this)); + } + + void <%- camelize(type) %>Layer::registerNative(jni::JNIEnv& env) { + mbgl::Log::Debug(mbgl::Event::JNI, "Registering native background layer"); + + //Lookup the class + <%- camelize(type) %>Layer::javaClass = *jni::Class<<%- camelize(type) %>Layer>::Find(env).NewGlobalRef(env).release(); + + #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name) + + //Register the peer + jni::RegisterNativePeer<<%- camelize(type) %>Layer>( + env, <%- camelize(type) %>Layer::javaClass, "nativePtr", +<% if (type === 'background') { -%> + std::make_unique<<%- camelize(type) %>Layer, JNIEnv&, jni::String>, +<% } else { -%> + std::make_unique<<%- camelize(type) %>Layer, JNIEnv&, jni::String, jni::String>, +<% } -%> + "initialize", + "finalize" + ); + + } + +} // namespace android +} // namespace mbgl diff --git a/platform/android/scripts/layer.hpp.ejs b/platform/android/scripts/layer.hpp.ejs new file mode 100644 index 0000000000..f735e3e35c --- /dev/null +++ b/platform/android/scripts/layer.hpp.ejs @@ -0,0 +1,38 @@ +<% + const type = locals.type; +-%> +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. + +#pragma once + +#include "layer.hpp" +#include <mbgl/style/layers/<%- type %>_layer.hpp> +#include <jni/jni.hpp> + +namespace mbgl { +namespace android { + +class <%- camelize(type) %>Layer : public Layer { +public: + + static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/<%- camelize(type) %>Layer"; }; + + static jni::Class<<%- camelize(type) %>Layer> javaClass; + + static void registerNative(jni::JNIEnv&); + +<% if (type === 'background') { -%> + <%- camelize(type) %>Layer(jni::JNIEnv&, jni::String); +<% } else { -%> + <%- camelize(type) %>Layer(jni::JNIEnv&, jni::String, jni::String); +<% } -%> + + <%- camelize(type) %>Layer(mbgl::Map&, mbgl::style::<%- camelize(type) %>Layer&); + + ~<%- camelize(type) %>Layer(); + + jni::jobject* createJavaPeer(jni::JNIEnv&); +}; + +} // namespace android +} // namespace mbgl diff --git a/platform/android/scripts/layer.java.ejs b/platform/android/scripts/layer.java.ejs new file mode 100644 index 0000000000..a5ca4c0521 --- /dev/null +++ b/platform/android/scripts/layer.java.ejs @@ -0,0 +1,44 @@ +<% + const type = locals.type; +-%> +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. +package com.mapbox.mapboxsdk.style.layers; + +/** + * <%- camelize(type) %> Layer + */ +public class <%- camelize(type) %>Layer extends Layer { + + public <%- camelize(type) %>Layer(long nativePtr) { + super(nativePtr); + } + +<% if (type === 'background') { -%> + public <%- camelize(type) %>Layer(String layerId) { + initialize(layerId); + } + + protected native void initialize(String layerId); +<% } else { -%> + public <%- camelize(type) %>Layer(String layerId, String sourceId) { + initialize(layerId, sourceId); + } + + protected native void initialize(String layerId, String sourceId); + + public void setSourceLayer(String sourceLayer) { + nativeSetSourceLayer(sourceLayer); + } +<% } -%> + +<% if (type !== 'background' && type !== 'raster') { -%> + public void setFilter(Filter.Statement filter) { + this.setFilter(filter.toArray()); + } + + public void setFilter(Object[] filter) { + nativeSetFilter(filter); + } + +<% } -%> +} diff --git a/platform/android/scripts/layer_property.java.ejs b/platform/android/scripts/layer_property.java.ejs new file mode 100644 index 0000000000..7119feeef2 --- /dev/null +++ b/platform/android/scripts/layer_property.java.ejs @@ -0,0 +1,42 @@ +<% + const properties = locals.properties; +-%> +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. +package com.mapbox.mapboxsdk.style.layers; + +import android.support.annotation.StringDef; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Paint/Layout properties for Layer + */ +public abstract class Property<T> { + +<% for (const property of properties) { -%> + //<%- property.name %> +<% for (const value of property.values) { -%> + public static final String <%- snakeCaseUpper(property.name) %>_<%- snakeCaseUpper(value) %> = "<%- value %>"; +<% } -%> + + @StringDef({ + <% for (const value of property.values) { -%> + <%- snakeCaseUpper(property.name) %>_<%- snakeCaseUpper(value) %>, + <% } -%> + }) + @Retention(RetentionPolicy.SOURCE) + public @interface <%- snakeCaseUpper(property.name) %> {} + +<% } -%> + + //Class definition + public final String name; + public final T value; + + /* package */ Property(String name, T value) { + this.name = name; + this.value = value; + } + +} diff --git a/platform/android/scripts/layer_property_factory.java.ejs b/platform/android/scripts/layer_property_factory.java.ejs new file mode 100644 index 0000000000..045f206d3f --- /dev/null +++ b/platform/android/scripts/layer_property_factory.java.ejs @@ -0,0 +1,45 @@ +<% + const paintProperties = locals.paintProperties; + const layoutProperties = locals.layoutProperties; +-%> +// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`. +package com.mapbox.mapboxsdk.style.layers; + +import android.annotation.SuppressLint; +import android.support.annotation.ColorInt; + +/** + * Constructs paint/layout properties for Layers + * @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#layers>Layer style documentation</a> + * + */ +public class PropertyFactory { + + public static Property<String> visibility(Boolean visible) { + return new LayoutProperty<>("visibility", visible? "visible": "none"); + } + +<% for (const property of paintProperties) { -%> +<% if (property.type == 'color') { -%> + public static Property<String> <%- camelizeWithLeadingLowercase(property.name) %>(@ColorInt int value) { + return new PaintProperty<>("<%- property.name %>", colorToRgbaString(value)); + } + +<% } -%> + public static Property<<%- propertyType(property) %>> <%- camelizeWithLeadingLowercase(property.name) %>(<%- propertyTypeAnnotation(property) %><%- iff(() => propertyTypeAnnotation(property), " ") %><%- propertyType(property) %> value) { + return new PaintProperty<>("<%- property.name %>", value); + } + +<% } -%> +<% for (const property of layoutProperties) { -%> + public static Property<<%- propertyType(property) %>> <%- camelizeWithLeadingLowercase(property.name) %>(<%- propertyTypeAnnotation(property) %><%- iff(() => propertyTypeAnnotation(property), " ") %><%- propertyType(property) %> value) { + return new LayoutProperty<>("<%- property.name %>", value); + } + +<% } -%> + @SuppressLint("DefaultLocale") + static String colorToRgbaString(@ColorInt int value) { + return String.format("rgba(%d, %d, %d, %d)", (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF, (value >> 24) & 0xFF); + } + +} |