[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
This commit is contained in:
Ivo van Dongen
2016-07-08 18:31:55 +02:00
parent b3c914fb3f
commit 9a3eadfd5b
60 changed files with 5510 additions and 2 deletions

View File

@@ -167,6 +167,9 @@ idocument:
ANDROID_ENV = platform/android/scripts/toolchain.sh
ANDROID_ABIS = arm-v5 arm-v7 arm-v8 x86 x86-64 mips
style-code-android:
node platform/android/scripts/generate-style-code.js
define ANDROID_RULES
build/android-$1/config.gypi: platform/android/scripts/configure.sh $(CONFIG_DEPENDENCIES)
$$(shell $(ANDROID_ENV) $1) ./configure $$< $$@ android $1
@@ -178,7 +181,7 @@ build/android-$1/Makefile: platform/android/platform.gyp build/android-$1/config
android-lib-$1: build/android-$1/Makefile
$$(shell $(ANDROID_ENV) $1) $(MAKE) -j$(JOBS) -C build/android-$1 all
android-$1: android-lib-$1
android-$1: android-lib-$1 style-code-android
cd platform/android && ./gradlew --parallel --max-workers=$(JOBS) assemble$(BUILDTYPE)
apackage: android-lib-$1

View File

@@ -2660,6 +2660,10 @@ public class MapView extends FrameLayout {
return mMyLocationView;
}
NativeMapView getNativeMapView() {
return mNativeMapView;
}
@UiThread
void snapshot(@NonNull final MapboxMap.SnapshotReadyCallback callback, @Nullable final Bitmap bitmap) {
TextureView textureView = (TextureView) findViewById(R.id.textureView);

View File

@@ -40,6 +40,9 @@ import com.mapbox.mapboxsdk.constants.Style;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.layers.CustomLayer;
import com.mapbox.mapboxsdk.maps.widgets.MyLocationViewSettings;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.NoSuchLayerException;
import com.mapbox.mapboxsdk.style.sources.Source;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
@@ -103,6 +106,39 @@ public class MapboxMap {
mMarkerViewManager = new MarkerViewManager(this, mapView);
}
// Style
@Nullable
@UiThread
public Layer getLayer(@NonNull String layerId) {
return getMapView().getNativeMapView().getLayer(layerId);
}
@UiThread
public void addLayer(@NonNull Layer layer) {
addLayer(layer, null);
}
@UiThread
public void addLayer(@NonNull Layer layer, String before) {
getMapView().getNativeMapView().addLayer(layer, before);
}
@UiThread
public void removeLayer(@NonNull String layerId) throws NoSuchLayerException {
getMapView().getNativeMapView().removeLayer(layerId);
}
@UiThread
public void addSource(@NonNull Source source) {
getMapView().getNativeMapView().addSource(source);
}
@UiThread
public void removeSource(@NonNull String sourceId) {
getMapView().getNativeMapView().removeSource(sourceId);
}
//
// MinZoom
//

View File

@@ -5,6 +5,8 @@ import android.content.Context;
import android.graphics.PointF;
import android.graphics.RectF;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.Surface;
import com.mapbox.mapboxsdk.annotations.Icon;
@@ -16,6 +18,9 @@ import com.mapbox.mapboxsdk.geometry.LatLngBounds;
import com.mapbox.mapboxsdk.geometry.ProjectedMeters;
import com.mapbox.mapboxsdk.layers.CustomLayer;
import com.mapbox.mapboxsdk.offline.OfflineManager;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.NoSuchLayerException;
import com.mapbox.mapboxsdk.style.sources.Source;
import java.util.List;
@@ -470,6 +475,28 @@ final class NativeMapView {
return nativeGetCameraValues(mNativeMapViewPtr);
}
// Runtime style Api
public Layer getLayer(String layerId) {
return nativeGetLayer(mNativeMapViewPtr, layerId);
}
public void addLayer(@NonNull Layer layer, @Nullable String before) {
nativeAddLayer(mNativeMapViewPtr, layer.getNativePtr(), before);
}
public void removeLayer(@NonNull String layerId) throws NoSuchLayerException {
nativeRemoveLayer(mNativeMapViewPtr, layerId);
}
public void addSource(@NonNull Source source) {
nativeAddSource(mNativeMapViewPtr, source.getId(), source);
}
public void removeSource(@NonNull String sourceId) {
nativeRemoveSource(mNativeMapViewPtr, sourceId);
}
//
// Callbacks
//
@@ -633,7 +660,7 @@ final class NativeMapView {
private native LatLng nativeLatLngForPixel(long nativeMapViewPtr, float x, float y);
private native double nativeGetTopOffsetPixelsForAnnotationSymbol(long nativeMapViewPtr, String symbolName);
private native void nativeJumpTo(long nativeMapViewPtr, double angle, double latitude, double longitude, double pitch, double zoom);
private native void nativeEaseTo(long nativeMapViewPtr, double angle, double latitude, double longitude, long duration, double pitch, double zoom, boolean easingInterpolator);
@@ -645,4 +672,14 @@ final class NativeMapView {
private native void nativeRemoveCustomLayer(long nativeMapViewPtr, String id);
private native double[] nativeGetCameraValues(long mNativeMapViewPtr);
private native Layer nativeGetLayer(long nativeMapViewPtr, String layerId);
private native void nativeAddLayer(long nativeMapViewPtr, long layerPtr, String before);
private native void nativeRemoveLayer(long nativeMapViewPtr, String layerId) throws NoSuchLayerException;
private native void nativeAddSource(long mNativeMapViewPtr, String id, Source source);
private native void nativeRemoveSource(long mNativeMapViewPtr, String sourceId);
}

View File

@@ -0,0 +1,19 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.style.layers;
/**
* Background Layer
*/
public class BackgroundLayer extends Layer {
public BackgroundLayer(long nativePtr) {
super(nativePtr);
}
public BackgroundLayer(String layerId) {
initialize(layerId);
}
protected native void initialize(String layerId);
}

View File

@@ -0,0 +1,31 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.style.layers;
/**
* Circle Layer
*/
public class CircleLayer extends Layer {
public CircleLayer(long nativePtr) {
super(nativePtr);
}
public CircleLayer(String layerId, String sourceId) {
initialize(layerId, sourceId);
}
protected native void initialize(String layerId, String sourceId);
public void setSourceLayer(String sourceLayer) {
nativeSetSourceLayer(sourceLayer);
}
public void setFilter(Filter.Statement filter) {
this.setFilter(filter.toArray());
}
public void setFilter(Object[] filter) {
nativeSetFilter(filter);
}
}

View File

@@ -0,0 +1,31 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.style.layers;
/**
* Fill Layer
*/
public class FillLayer extends Layer {
public FillLayer(long nativePtr) {
super(nativePtr);
}
public FillLayer(String layerId, String sourceId) {
initialize(layerId, sourceId);
}
protected native void initialize(String layerId, String sourceId);
public void setSourceLayer(String sourceLayer) {
nativeSetSourceLayer(sourceLayer);
}
public void setFilter(Filter.Statement filter) {
this.setFilter(filter.toArray());
}
public void setFilter(Object[] filter) {
nativeSetFilter(filter);
}
}

View File

@@ -0,0 +1,115 @@
package com.mapbox.mapboxsdk.style.layers;
import java.util.ArrayList;
import java.util.Arrays;
/**
* Utility to build filter expressions more easily:
*
* @see <a href="https://www.mapbox.com/mapbox-gl-style-spec/#types-filter">Style spec</a>
*/
public class Filter {
public abstract static class Statement {
protected final String operator;
public Statement(String operator) {
this.operator = operator;
}
public abstract Object[] toArray();
}
public static class SimpleStatement extends Statement {
private final String key;
private final Object[] values;
public SimpleStatement(String operator, String key, Object... values) {
super(operator);
this.key = key;
this.values = values;
}
@Override
public Object[] toArray() {
ArrayList<Object> array = new ArrayList<>(2 + values.length);
array.add(operator);
array.add(key);
array.addAll(Arrays.asList(values));
return array.toArray();
}
}
public static class CompoundStatement extends Statement {
private final Statement[] statements;
public CompoundStatement(String operator, Statement... statements) {
super(operator);
this.statements = statements;
}
@Override
public Object[] toArray() {
ArrayList<Object> array = new ArrayList<>(1 + statements.length);
array.add(operator);
for (Statement statement : statements) {
array.add(statement.toArray());
}
return array.toArray();
}
}
public static Statement all(Statement... statements) {
return new CompoundStatement("all", statements);
}
public static Statement any(Statement... statements) {
return new CompoundStatement("any", statements);
}
public static Statement none(Statement... statements) {
return new CompoundStatement("none", statements);
}
public static Statement has(String key) {
return new SimpleStatement("has", key);
}
public static Statement notHas(String key) {
return new SimpleStatement("!has", key);
}
public static Statement eq(String key, Object value) {
return new SimpleStatement("==", key, value);
}
public static Statement neq(String key, Object value) {
return new SimpleStatement("!=", key, value);
}
public static Statement gt(String key, Object value) {
return new SimpleStatement(">", key, value);
}
public static Statement gte(String key, Object value) {
return new SimpleStatement(">=", key, value);
}
public static Statement lt(String key, Object value) {
return new SimpleStatement("<", key, value);
}
public static Statement lte(String key, Object value) {
return new SimpleStatement("<=", key, value);
}
public static Statement in(String key, Object... values) {
return new SimpleStatement("in", key, values);
}
public static Statement notIn(String key, Object... values) {
return new SimpleStatement("!in", key, values);
}
}

View File

@@ -0,0 +1,68 @@
package com.mapbox.mapboxsdk.style.layers;
import android.support.annotation.NonNull;
import android.util.Log;
/**
* Base class for the different Layer types
*/
public abstract class Layer {
private long nativePtr;
public Layer(long nativePtr) {
Log.i(Layer.class.getSimpleName(), "Native pointer constructor: " + nativePtr);
this.nativePtr = nativePtr;
}
public Layer() {
Log.i(Layer.class.getSimpleName(), "Default constructor");
}
public void set(@NonNull Property<?>... properties) {
if (properties.length == 0) {
return;
}
boolean updateClasses = false;
for (Property<?> property : properties) {
if (property instanceof PaintProperty) {
updateClasses = true;
nativeSetPaintProperty(property.name, property.value);
} else {
nativeSetLayoutProperty(property.name, property.value);
}
}
nativeUpdateStyle(updateClasses);
}
public String getId() {
return nativeGetId();
}
@Override
protected native void finalize() throws Throwable;
protected native String nativeGetId();
protected native void nativeSetLayoutProperty(String name, Object value);
protected native void nativeSetPaintProperty(String name, Object value);
protected native void nativeSetFilter(Object[] filter);
protected native void nativeSetSourceLayer(String sourceLayer);
protected native void nativeUpdateStyle(boolean updateClasses);
@Override
public String toString() {
return "Layer: " + getId();
}
public long getNativePtr() {
return nativePtr;
}
}

View File

@@ -0,0 +1,9 @@
package com.mapbox.mapboxsdk.style.layers;
class LayoutProperty<T> extends Property<T> {
LayoutProperty(String name, T value) {
super(name, value);
}
}

View File

@@ -0,0 +1,31 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.style.layers;
/**
* Line Layer
*/
public class LineLayer extends Layer {
public LineLayer(long nativePtr) {
super(nativePtr);
}
public LineLayer(String layerId, String sourceId) {
initialize(layerId, sourceId);
}
protected native void initialize(String layerId, String sourceId);
public void setSourceLayer(String sourceLayer) {
nativeSetSourceLayer(sourceLayer);
}
public void setFilter(Filter.Statement filter) {
this.setFilter(filter.toArray());
}
public void setFilter(Object[] filter) {
nativeSetFilter(filter);
}
}

View File

@@ -0,0 +1,11 @@
package com.mapbox.mapboxsdk.style.layers;
/**
* No such layer.
*/
public class NoSuchLayerException extends Exception {
public NoSuchLayerException(String message) {
super(message);
}
}

View File

@@ -0,0 +1,9 @@
package com.mapbox.mapboxsdk.style.layers;
class PaintProperty<T> extends Property<T> {
PaintProperty(String name, T value) {
super(name, value);
}
}

View File

@@ -0,0 +1,226 @@
// 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> {
//line-cap
public static final String LINE_CAP_BUTT = "butt";
public static final String LINE_CAP_ROUND = "round";
public static final String LINE_CAP_SQUARE = "square";
@StringDef({
LINE_CAP_BUTT,
LINE_CAP_ROUND,
LINE_CAP_SQUARE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface LINE_CAP {}
//line-join
public static final String LINE_JOIN_BEVEL = "bevel";
public static final String LINE_JOIN_ROUND = "round";
public static final String LINE_JOIN_MITER = "miter";
@StringDef({
LINE_JOIN_BEVEL,
LINE_JOIN_ROUND,
LINE_JOIN_MITER,
})
@Retention(RetentionPolicy.SOURCE)
public @interface LINE_JOIN {}
//symbol-placement
public static final String SYMBOL_PLACEMENT_POINT = "point";
public static final String SYMBOL_PLACEMENT_LINE = "line";
@StringDef({
SYMBOL_PLACEMENT_POINT,
SYMBOL_PLACEMENT_LINE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface SYMBOL_PLACEMENT {}
//icon-rotation-alignment
public static final String ICON_ROTATION_ALIGNMENT_MAP = "map";
public static final String ICON_ROTATION_ALIGNMENT_VIEWPORT = "viewport";
@StringDef({
ICON_ROTATION_ALIGNMENT_MAP,
ICON_ROTATION_ALIGNMENT_VIEWPORT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ICON_ROTATION_ALIGNMENT {}
//icon-text-fit
public static final String ICON_TEXT_FIT_NONE = "none";
public static final String ICON_TEXT_FIT_BOTH = "both";
public static final String ICON_TEXT_FIT_WIDTH = "width";
public static final String ICON_TEXT_FIT_HEIGHT = "height";
@StringDef({
ICON_TEXT_FIT_NONE,
ICON_TEXT_FIT_BOTH,
ICON_TEXT_FIT_WIDTH,
ICON_TEXT_FIT_HEIGHT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ICON_TEXT_FIT {}
//text-pitch-alignment
public static final String TEXT_PITCH_ALIGNMENT_MAP = "map";
public static final String TEXT_PITCH_ALIGNMENT_VIEWPORT = "viewport";
@StringDef({
TEXT_PITCH_ALIGNMENT_MAP,
TEXT_PITCH_ALIGNMENT_VIEWPORT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface TEXT_PITCH_ALIGNMENT {}
//text-rotation-alignment
public static final String TEXT_ROTATION_ALIGNMENT_MAP = "map";
public static final String TEXT_ROTATION_ALIGNMENT_VIEWPORT = "viewport";
@StringDef({
TEXT_ROTATION_ALIGNMENT_MAP,
TEXT_ROTATION_ALIGNMENT_VIEWPORT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface TEXT_ROTATION_ALIGNMENT {}
//text-justify
public static final String TEXT_JUSTIFY_LEFT = "left";
public static final String TEXT_JUSTIFY_CENTER = "center";
public static final String TEXT_JUSTIFY_RIGHT = "right";
@StringDef({
TEXT_JUSTIFY_LEFT,
TEXT_JUSTIFY_CENTER,
TEXT_JUSTIFY_RIGHT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface TEXT_JUSTIFY {}
//text-anchor
public static final String TEXT_ANCHOR_CENTER = "center";
public static final String TEXT_ANCHOR_LEFT = "left";
public static final String TEXT_ANCHOR_RIGHT = "right";
public static final String TEXT_ANCHOR_TOP = "top";
public static final String TEXT_ANCHOR_BOTTOM = "bottom";
public static final String TEXT_ANCHOR_TOP_LEFT = "top-left";
public static final String TEXT_ANCHOR_TOP_RIGHT = "top-right";
public static final String TEXT_ANCHOR_BOTTOM_LEFT = "bottom-left";
public static final String TEXT_ANCHOR_BOTTOM_RIGHT = "bottom-right";
@StringDef({
TEXT_ANCHOR_CENTER,
TEXT_ANCHOR_LEFT,
TEXT_ANCHOR_RIGHT,
TEXT_ANCHOR_TOP,
TEXT_ANCHOR_BOTTOM,
TEXT_ANCHOR_TOP_LEFT,
TEXT_ANCHOR_TOP_RIGHT,
TEXT_ANCHOR_BOTTOM_LEFT,
TEXT_ANCHOR_BOTTOM_RIGHT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface TEXT_ANCHOR {}
//text-transform
public static final String TEXT_TRANSFORM_NONE = "none";
public static final String TEXT_TRANSFORM_UPPERCASE = "uppercase";
public static final String TEXT_TRANSFORM_LOWERCASE = "lowercase";
@StringDef({
TEXT_TRANSFORM_NONE,
TEXT_TRANSFORM_UPPERCASE,
TEXT_TRANSFORM_LOWERCASE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface TEXT_TRANSFORM {}
//fill-translate-anchor
public static final String FILL_TRANSLATE_ANCHOR_MAP = "map";
public static final String FILL_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
@StringDef({
FILL_TRANSLATE_ANCHOR_MAP,
FILL_TRANSLATE_ANCHOR_VIEWPORT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface FILL_TRANSLATE_ANCHOR {}
//line-translate-anchor
public static final String LINE_TRANSLATE_ANCHOR_MAP = "map";
public static final String LINE_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
@StringDef({
LINE_TRANSLATE_ANCHOR_MAP,
LINE_TRANSLATE_ANCHOR_VIEWPORT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface LINE_TRANSLATE_ANCHOR {}
//icon-translate-anchor
public static final String ICON_TRANSLATE_ANCHOR_MAP = "map";
public static final String ICON_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
@StringDef({
ICON_TRANSLATE_ANCHOR_MAP,
ICON_TRANSLATE_ANCHOR_VIEWPORT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ICON_TRANSLATE_ANCHOR {}
//text-translate-anchor
public static final String TEXT_TRANSLATE_ANCHOR_MAP = "map";
public static final String TEXT_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
@StringDef({
TEXT_TRANSLATE_ANCHOR_MAP,
TEXT_TRANSLATE_ANCHOR_VIEWPORT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface TEXT_TRANSLATE_ANCHOR {}
//circle-translate-anchor
public static final String CIRCLE_TRANSLATE_ANCHOR_MAP = "map";
public static final String CIRCLE_TRANSLATE_ANCHOR_VIEWPORT = "viewport";
@StringDef({
CIRCLE_TRANSLATE_ANCHOR_MAP,
CIRCLE_TRANSLATE_ANCHOR_VIEWPORT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface CIRCLE_TRANSLATE_ANCHOR {}
//circle-pitch-scale
public static final String CIRCLE_PITCH_SCALE_MAP = "map";
public static final String CIRCLE_PITCH_SCALE_VIEWPORT = "viewport";
@StringDef({
CIRCLE_PITCH_SCALE_MAP,
CIRCLE_PITCH_SCALE_VIEWPORT,
})
@Retention(RetentionPolicy.SOURCE)
public @interface CIRCLE_PITCH_SCALE {}
//Class definition
public final String name;
public final T value;
/* package */ Property(String name, T value) {
this.name = name;
this.value = value;
}
}

View File

@@ -0,0 +1,403 @@
// 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");
}
public static Property<Boolean> fillAntialias(Boolean value) {
return new PaintProperty<>("fill-antialias", value);
}
public static Property<Float> fillOpacity(Float value) {
return new PaintProperty<>("fill-opacity", value);
}
public static Property<String> fillColor(@ColorInt int value) {
return new PaintProperty<>("fill-color", colorToRgbaString(value));
}
public static Property<String> fillColor(String value) {
return new PaintProperty<>("fill-color", value);
}
public static Property<String> fillOutlineColor(@ColorInt int value) {
return new PaintProperty<>("fill-outline-color", colorToRgbaString(value));
}
public static Property<String> fillOutlineColor(String value) {
return new PaintProperty<>("fill-outline-color", value);
}
public static Property<Float[]> fillTranslate(Float[] value) {
return new PaintProperty<>("fill-translate", value);
}
public static Property<String> fillTranslateAnchor(@Property.FILL_TRANSLATE_ANCHOR String value) {
return new PaintProperty<>("fill-translate-anchor", value);
}
public static Property<String> fillPattern(String value) {
return new PaintProperty<>("fill-pattern", value);
}
public static Property<Float> lineOpacity(Float value) {
return new PaintProperty<>("line-opacity", value);
}
public static Property<String> lineColor(@ColorInt int value) {
return new PaintProperty<>("line-color", colorToRgbaString(value));
}
public static Property<String> lineColor(String value) {
return new PaintProperty<>("line-color", value);
}
public static Property<Float[]> lineTranslate(Float[] value) {
return new PaintProperty<>("line-translate", value);
}
public static Property<String> lineTranslateAnchor(@Property.LINE_TRANSLATE_ANCHOR String value) {
return new PaintProperty<>("line-translate-anchor", value);
}
public static Property<Float> lineWidth(Float value) {
return new PaintProperty<>("line-width", value);
}
public static Property<Float> lineGapWidth(Float value) {
return new PaintProperty<>("line-gap-width", value);
}
public static Property<Float> lineOffset(Float value) {
return new PaintProperty<>("line-offset", value);
}
public static Property<Float> lineBlur(Float value) {
return new PaintProperty<>("line-blur", value);
}
public static Property<Float[]> lineDasharray(Float[] value) {
return new PaintProperty<>("line-dasharray", value);
}
public static Property<String> linePattern(String value) {
return new PaintProperty<>("line-pattern", value);
}
public static Property<Float> iconOpacity(Float value) {
return new PaintProperty<>("icon-opacity", value);
}
public static Property<String> iconColor(@ColorInt int value) {
return new PaintProperty<>("icon-color", colorToRgbaString(value));
}
public static Property<String> iconColor(String value) {
return new PaintProperty<>("icon-color", value);
}
public static Property<String> iconHaloColor(@ColorInt int value) {
return new PaintProperty<>("icon-halo-color", colorToRgbaString(value));
}
public static Property<String> iconHaloColor(String value) {
return new PaintProperty<>("icon-halo-color", value);
}
public static Property<Float> iconHaloWidth(Float value) {
return new PaintProperty<>("icon-halo-width", value);
}
public static Property<Float> iconHaloBlur(Float value) {
return new PaintProperty<>("icon-halo-blur", value);
}
public static Property<Float[]> iconTranslate(Float[] value) {
return new PaintProperty<>("icon-translate", value);
}
public static Property<String> iconTranslateAnchor(@Property.ICON_TRANSLATE_ANCHOR String value) {
return new PaintProperty<>("icon-translate-anchor", value);
}
public static Property<Float> textOpacity(Float value) {
return new PaintProperty<>("text-opacity", value);
}
public static Property<String> textColor(@ColorInt int value) {
return new PaintProperty<>("text-color", colorToRgbaString(value));
}
public static Property<String> textColor(String value) {
return new PaintProperty<>("text-color", value);
}
public static Property<String> textHaloColor(@ColorInt int value) {
return new PaintProperty<>("text-halo-color", colorToRgbaString(value));
}
public static Property<String> textHaloColor(String value) {
return new PaintProperty<>("text-halo-color", value);
}
public static Property<Float> textHaloWidth(Float value) {
return new PaintProperty<>("text-halo-width", value);
}
public static Property<Float> textHaloBlur(Float value) {
return new PaintProperty<>("text-halo-blur", value);
}
public static Property<Float[]> textTranslate(Float[] value) {
return new PaintProperty<>("text-translate", value);
}
public static Property<String> textTranslateAnchor(@Property.TEXT_TRANSLATE_ANCHOR String value) {
return new PaintProperty<>("text-translate-anchor", value);
}
public static Property<Float> circleRadius(Float value) {
return new PaintProperty<>("circle-radius", value);
}
public static Property<String> circleColor(@ColorInt int value) {
return new PaintProperty<>("circle-color", colorToRgbaString(value));
}
public static Property<String> circleColor(String value) {
return new PaintProperty<>("circle-color", value);
}
public static Property<Float> circleBlur(Float value) {
return new PaintProperty<>("circle-blur", value);
}
public static Property<Float> circleOpacity(Float value) {
return new PaintProperty<>("circle-opacity", value);
}
public static Property<Float[]> circleTranslate(Float[] value) {
return new PaintProperty<>("circle-translate", value);
}
public static Property<String> circleTranslateAnchor(@Property.CIRCLE_TRANSLATE_ANCHOR String value) {
return new PaintProperty<>("circle-translate-anchor", value);
}
public static Property<String> circlePitchScale(@Property.CIRCLE_PITCH_SCALE String value) {
return new PaintProperty<>("circle-pitch-scale", value);
}
public static Property<Float> rasterOpacity(Float value) {
return new PaintProperty<>("raster-opacity", value);
}
public static Property<Float> rasterHueRotate(Float value) {
return new PaintProperty<>("raster-hue-rotate", value);
}
public static Property<Float> rasterBrightnessMin(Float value) {
return new PaintProperty<>("raster-brightness-min", value);
}
public static Property<Float> rasterBrightnessMax(Float value) {
return new PaintProperty<>("raster-brightness-max", value);
}
public static Property<Float> rasterSaturation(Float value) {
return new PaintProperty<>("raster-saturation", value);
}
public static Property<Float> rasterContrast(Float value) {
return new PaintProperty<>("raster-contrast", value);
}
public static Property<Float> rasterFadeDuration(Float value) {
return new PaintProperty<>("raster-fade-duration", value);
}
public static Property<String> backgroundColor(@ColorInt int value) {
return new PaintProperty<>("background-color", colorToRgbaString(value));
}
public static Property<String> backgroundColor(String value) {
return new PaintProperty<>("background-color", value);
}
public static Property<String> backgroundPattern(String value) {
return new PaintProperty<>("background-pattern", value);
}
public static Property<Float> backgroundOpacity(Float value) {
return new PaintProperty<>("background-opacity", value);
}
public static Property<String> lineCap(@Property.LINE_CAP String value) {
return new LayoutProperty<>("line-cap", value);
}
public static Property<String> lineJoin(@Property.LINE_JOIN String value) {
return new LayoutProperty<>("line-join", value);
}
public static Property<Float> lineMiterLimit(Float value) {
return new LayoutProperty<>("line-miter-limit", value);
}
public static Property<Float> lineRoundLimit(Float value) {
return new LayoutProperty<>("line-round-limit", value);
}
public static Property<String> symbolPlacement(@Property.SYMBOL_PLACEMENT String value) {
return new LayoutProperty<>("symbol-placement", value);
}
public static Property<Float> symbolSpacing(Float value) {
return new LayoutProperty<>("symbol-spacing", value);
}
public static Property<Boolean> symbolAvoidEdges(Boolean value) {
return new LayoutProperty<>("symbol-avoid-edges", value);
}
public static Property<Boolean> iconAllowOverlap(Boolean value) {
return new LayoutProperty<>("icon-allow-overlap", value);
}
public static Property<Boolean> iconIgnorePlacement(Boolean value) {
return new LayoutProperty<>("icon-ignore-placement", value);
}
public static Property<Boolean> iconOptional(Boolean value) {
return new LayoutProperty<>("icon-optional", value);
}
public static Property<String> iconRotationAlignment(@Property.ICON_ROTATION_ALIGNMENT String value) {
return new LayoutProperty<>("icon-rotation-alignment", value);
}
public static Property<Float> iconSize(Float value) {
return new LayoutProperty<>("icon-size", value);
}
public static Property<String> iconTextFit(@Property.ICON_TEXT_FIT String value) {
return new LayoutProperty<>("icon-text-fit", value);
}
public static Property<Float[]> iconTextFitPadding(Float[] value) {
return new LayoutProperty<>("icon-text-fit-padding", value);
}
public static Property<String> iconImage(String value) {
return new LayoutProperty<>("icon-image", value);
}
public static Property<Float> iconRotate(Float value) {
return new LayoutProperty<>("icon-rotate", value);
}
public static Property<Float> iconPadding(Float value) {
return new LayoutProperty<>("icon-padding", value);
}
public static Property<Boolean> iconKeepUpright(Boolean value) {
return new LayoutProperty<>("icon-keep-upright", value);
}
public static Property<Float[]> iconOffset(Float[] value) {
return new LayoutProperty<>("icon-offset", value);
}
public static Property<String> textPitchAlignment(@Property.TEXT_PITCH_ALIGNMENT String value) {
return new LayoutProperty<>("text-pitch-alignment", value);
}
public static Property<String> textRotationAlignment(@Property.TEXT_ROTATION_ALIGNMENT String value) {
return new LayoutProperty<>("text-rotation-alignment", value);
}
public static Property<String> textField(String value) {
return new LayoutProperty<>("text-field", value);
}
public static Property<String[]> textFont(String[] value) {
return new LayoutProperty<>("text-font", value);
}
public static Property<Float> textSize(Float value) {
return new LayoutProperty<>("text-size", value);
}
public static Property<Float> textMaxWidth(Float value) {
return new LayoutProperty<>("text-max-width", value);
}
public static Property<Float> textLineHeight(Float value) {
return new LayoutProperty<>("text-line-height", value);
}
public static Property<Float> textLetterSpacing(Float value) {
return new LayoutProperty<>("text-letter-spacing", value);
}
public static Property<String> textJustify(@Property.TEXT_JUSTIFY String value) {
return new LayoutProperty<>("text-justify", value);
}
public static Property<String> textAnchor(@Property.TEXT_ANCHOR String value) {
return new LayoutProperty<>("text-anchor", value);
}
public static Property<Float> textMaxAngle(Float value) {
return new LayoutProperty<>("text-max-angle", value);
}
public static Property<Float> textRotate(Float value) {
return new LayoutProperty<>("text-rotate", value);
}
public static Property<Float> textPadding(Float value) {
return new LayoutProperty<>("text-padding", value);
}
public static Property<Boolean> textKeepUpright(Boolean value) {
return new LayoutProperty<>("text-keep-upright", value);
}
public static Property<String> textTransform(@Property.TEXT_TRANSFORM String value) {
return new LayoutProperty<>("text-transform", value);
}
public static Property<Float[]> textOffset(Float[] value) {
return new LayoutProperty<>("text-offset", value);
}
public static Property<Boolean> textAllowOverlap(Boolean value) {
return new LayoutProperty<>("text-allow-overlap", value);
}
public static Property<Boolean> textIgnorePlacement(Boolean value) {
return new LayoutProperty<>("text-ignore-placement", value);
}
public static Property<Boolean> textOptional(Boolean value) {
return new LayoutProperty<>("text-optional", 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);
}
}

View File

@@ -0,0 +1,23 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.style.layers;
/**
* Raster Layer
*/
public class RasterLayer extends Layer {
public RasterLayer(long nativePtr) {
super(nativePtr);
}
public RasterLayer(String layerId, String sourceId) {
initialize(layerId, sourceId);
}
protected native void initialize(String layerId, String sourceId);
public void setSourceLayer(String sourceLayer) {
nativeSetSourceLayer(sourceLayer);
}
}

View File

@@ -0,0 +1,31 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
package com.mapbox.mapboxsdk.style.layers;
/**
* Symbol Layer
*/
public class SymbolLayer extends Layer {
public SymbolLayer(long nativePtr) {
super(nativePtr);
}
public SymbolLayer(String layerId, String sourceId) {
initialize(layerId, sourceId);
}
protected native void initialize(String layerId, String sourceId);
public void setSourceLayer(String sourceLayer) {
nativeSetSourceLayer(sourceLayer);
}
public void setFilter(Filter.Statement filter) {
this.setFilter(filter.toArray());
}
public void setFilter(Object[] filter) {
nativeSetFilter(filter);
}
}

View File

@@ -0,0 +1,23 @@
package com.mapbox.mapboxsdk.style.sources;
import java.net.URL;
import java.util.HashMap;
public class GeoJsonSource extends Source {
public static final String TYPE = "geojson";
private static final String DATA_KEY = "data";
public GeoJsonSource(String id, String geoJson) {
super(id, TYPE);
//Wrap the String in a map as an Object is expected by the
//style conversion template
HashMap<String, String> wrapper = new HashMap<>();
wrapper.put(DATA_KEY, geoJson);
this.put(DATA_KEY, wrapper);
}
public GeoJsonSource(String id, URL url) {
super(id, TYPE);
this.put(DATA_KEY, url.toExternalForm());
}
}

View File

@@ -0,0 +1,17 @@
package com.mapbox.mapboxsdk.style.sources;
import java.net.URL;
public class RasterSource extends Source {
public static final String TYPE = "raster";
private static final String URL_KEY = "url";
public RasterSource(String id, URL url) {
this(id, url.toExternalForm());
}
public RasterSource(String id, String url) {
super(id, TYPE);
this.put(URL_KEY, url);
}
}

View File

@@ -0,0 +1,16 @@
package com.mapbox.mapboxsdk.style.sources;
import java.util.HashMap;
public abstract class Source extends HashMap<String, Object> {
private final String id;
protected Source(String id, String type) {
this.put("type", type);
this.id = id;
}
public String getId() {
return id;
}
}

View File

@@ -0,0 +1,18 @@
package com.mapbox.mapboxsdk.style.sources;
import java.net.URL;
import java.util.HashMap;
public class VectorSource extends Source {
public static final String TYPE = "vector";
private static final String URL_KEY = "url";
public VectorSource(String id, URL url) {
this(id, url.toExternalForm());
}
public VectorSource(String id, String url) {
super(id, TYPE);
this.put(URL_KEY, url);
}
}

View File

@@ -301,6 +301,14 @@
android:value="@string/category_fragment" />
</activity>
<activity android:name=".activity.style.RuntimeStyleActivity"
android:description="@string/description_runtime_style"
android:label="@string/activity_runtime_style">
<meta-data
android:name="@string/category"
android:value="@string/category_style" />
</activity>
<!-- Configuration Settings -->
<meta-data
android:name="com.mapbox.TestEventsServer"

View File

@@ -0,0 +1,299 @@
package com.mapbox.mapboxsdk.testapp.activity.style;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.RawRes;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import com.mapbox.mapboxsdk.camera.CameraUpdateFactory;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.style.layers.FillLayer;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.LineLayer;
import com.mapbox.mapboxsdk.style.layers.NoSuchLayerException;
import com.mapbox.mapboxsdk.style.layers.Property;
import com.mapbox.mapboxsdk.style.layers.RasterLayer;
import com.mapbox.mapboxsdk.style.sources.GeoJsonSource;
import com.mapbox.mapboxsdk.style.sources.RasterSource;
import com.mapbox.mapboxsdk.style.sources.Source;
import com.mapbox.mapboxsdk.style.sources.VectorSource;
import com.mapbox.mapboxsdk.testapp.R;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import static com.mapbox.mapboxsdk.style.layers.Filter.*;
import static com.mapbox.mapboxsdk.style.layers.Property.*;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.*;
/**
* Sample Activity to show a typical location picker use case
*/
public class RuntimeStyleActivity extends AppCompatActivity {
private static final String TAG = RuntimeStyleActivity.class.getSimpleName();
private MapView mapView;
private MapboxMap mapboxMap;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_runtime_style);
setupActionBar();
//Initialize map as normal
mapView = (MapView) findViewById(R.id.mapView);
mapView.onCreate(savedInstanceState);
mapView.getMapAsync(new OnMapReadyCallback() {
@Override
public void onMapReady(MapboxMap map) {
//Store for later
mapboxMap = map;
//Center and Zoom (Amsterdam, zoomed to streets)
mapboxMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(52.379189, 4.899431), 14));
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_runtime_style, menu);
return true;
}
@Override
public void onResume() {
super.onResume();
mapView.onResume();
}
@Override
public void onPause() {
super.onPause();
mapView.onPause();
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
mapView.onSaveInstanceState(outState);
}
@Override
protected void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
onBackPressed();
return true;
case R.id.action_water_color:
setWaterColor();
return true;
case R.id.action_background_opacity:
setBackgroundOpacity();
return true;
case R.id.action_road_avoid_edges:
setRoadSymbolPlacement();
return true;
case R.id.action_layer_visibility:
setLayerInvisible();
return true;
case R.id.action_remove_layer:
removeBuildings();
return true;
case R.id.action_add_parks_layer:
addParksLayer();
return true;
case R.id.action_add_terrain_layer:
addTerrainLayer();
return true;
case R.id.action_add_satellite_layer:
addSatelliteLayer();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void setLayerInvisible() {
String[] roadLayers = new String[]{"water"};
for (String roadLayer : roadLayers) {
Layer layer = mapboxMap.getLayer(roadLayer);
if (layer != null) {
layer.set(visibility(false));
}
}
}
private void setRoadSymbolPlacement() {
//Zoom so that the labels are visible first
mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(14), new DefaultCallback() {
@Override
public void onFinish() {
String[] roadLayers = new String[]{"road-label-small", "road-label-medium", "road-label-large"};
for (String roadLayer : roadLayers) {
Layer layer = mapboxMap.getLayer(roadLayer);
if (layer != null) {
layer.set(symbolPlacement(SYMBOL_PLACEMENT_POINT));
}
}
}
});
}
private void setBackgroundOpacity() {
Layer background = mapboxMap.getLayer("background");
if (background != null) {
background.set(backgroundOpacity(0.2f));
}
}
private void setWaterColor() {
Layer water = mapboxMap.getLayer("water");
if (water != null) {
water.set(
visibility(true),
fillColor(Color.RED)
);
} else {
Toast.makeText(RuntimeStyleActivity.this, "No water layer in this style", Toast.LENGTH_SHORT).show();
}
}
private void removeBuildings() {
//Zoom to see buildings first
try {
mapboxMap.removeLayer("building");
} catch (NoSuchLayerException e) {
Toast.makeText(RuntimeStyleActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
}
private void addParksLayer() {
//Add a source
Source source;
try {
source = new GeoJsonSource("amsterdam-spots", readRawResource(R.raw.amsterdam));
} catch (IOException e) {
Toast.makeText(RuntimeStyleActivity.this, "Couldn't add source: " + e.getMessage(), Toast.LENGTH_SHORT).show();
return;
}
mapboxMap.addSource(source);
FillLayer layer = new FillLayer("parksLayer", "amsterdam-spots");
layer.set(
fillColor(Color.RED),
fillOutlineColor(Color.BLUE),
fillOpacity(0.3f),
fillAntialias(true)
);
//Only show me parks
layer.setFilter(eq("type", "park"));
mapboxMap.addLayer(layer, "building");
//layer.setPaintProperty(fillColor(Color.RED)); //XXX But not after the object is attached
//Or get the object later and set it. It's all good.
mapboxMap.getLayer("parksLayer").set(fillColor(Color.RED));
//Get a good look at it all
mapboxMap.animateCamera(CameraUpdateFactory.zoomTo(12));
}
private void addTerrainLayer() {
//Add a source
Source source = new VectorSource("my-terrain-source", "mapbox://mapbox.mapbox-terrain-v2");
mapboxMap.addSource(source);
LineLayer layer = new LineLayer("terrainLayer", "my-terrain-source");
layer.setSourceLayer("contour");
layer.set(
lineJoin(Property.LINE_JOIN_ROUND),
lineCap(Property.LINE_CAP_ROUND),
lineColor(Color.RED),
lineWidth(20f)
);
mapboxMap.addLayer(layer);
}
private void addSatelliteLayer() {
//Add a source
Source source = new RasterSource("my-raster-source", "mapbox://mapbox.satellite");
mapboxMap.addSource(source);
//Add a layer
mapboxMap.addLayer(new RasterLayer("satellite-layer", "my-raster-source"));
}
private String readRawResource(@RawRes int rawResource) throws IOException {
InputStream is = getResources().openRawResource(rawResource);
Writer writer = new StringWriter();
char[] buffer = new char[1024];
try {
Reader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
int n;
while ((n = reader.read(buffer)) != -1) {
writer.write(buffer, 0, n);
}
} finally {
is.close();
}
return writer.toString();
}
private void setupActionBar() {
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setDisplayShowHomeEnabled(true);
}
}
private static class DefaultCallback implements MapboxMap.CancelableCallback {
@Override
public void onCancel() {
//noop
}
@Override
public void onFinish() {
//noop
}
}
}

View File

@@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/primary"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"/>
<com.mapbox.mapboxsdk.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/toolbar"/>
</RelativeLayout>

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:mapbox="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_water_color"
android:title="Color the water"
mapbox:showAsAction="never"/>
<item
android:id="@+id/action_background_opacity"
android:title="Set background opacity"
mapbox:showAsAction="never"/>
<item
android:id="@+id/action_road_avoid_edges"
android:title="Set road symbol placement to Point"
mapbox:showAsAction="never"/>
<item
android:id="@+id/action_layer_visibility"
android:title="Set layer visibility to false"
mapbox:showAsAction="never"/>
<item
android:id="@+id/action_add_parks_layer"
android:title="Add a parks layer"
mapbox:showAsAction="never"/>
<item
android:id="@+id/action_remove_layer"
android:title="Remove buildings layer"
mapbox:showAsAction="never"/>
<item
android:id="@+id/action_add_terrain_layer"
android:title="Add a terrain layer"
mapbox:showAsAction="never"/>
<item
android:id="@+id/action_add_satellite_layer"
android:title="Add a satellite layer"
mapbox:showAsAction="never"/>
</menu>

File diff suppressed because it is too large Load Diff

View File

@@ -54,6 +54,7 @@
<string name="activity_minmax_zoom">Min/Max Zoom</string>
<string name="activity_viewpager">ViewPager</string>
<string name="title_activity_navigation_drawer">Navigation Drawer</string>
<string name="activity_runtime_style">Runtime Style</string>
<!-- Description -->
<string name="description_user_location_tracking">Tracks the location of the user</string>
@@ -92,6 +93,7 @@
<string name="description_location_picker">Use a fixed Marker to select your location</string>
<string name="description_viewpager">Use SupportMapFragments in a ViewPager</string>
<string name="description_navigation_drawer">Test for Navigation Drawer support</string>
<string name="description_runtime_style">Adopt the map style on the fly</string>
<string name="menuitem_title_concurrent_infowindow">Concurrent Open InfoWindows</string>
<string name="menuitem_title_deselect_markers_on_tap">Deselect Markers On Tap</string>
@@ -112,6 +114,7 @@
<string name="category_offline">Offline</string>
<string name="category_userlocation">User Location</string>
<string name="category_navigation">Navigation</string>
<string name="category_style">Styling</string>
<string name="action_visible_bounds_explanation">Center map around 2 markers</string>
<string name="action_remove_polylines">Remove polylines</string>

View File

@@ -0,0 +1,90 @@
package com.mapbox.mapboxsdk.style.layers;
import org.junit.Test;
import static org.junit.Assert.*;
import static com.mapbox.mapboxsdk.style.layers.Filter.*;
/**
* Tests for Filter
*/
public class FilterTest {
@Test
public void testAll() {
assertArrayEquals(all().toArray(), new Object[]{"all"});
assertArrayEquals(
all(eq("key", 2), neq("key", 3)).toArray(),
new Object[]{"all", new Object[]{"==", "key", 2}, new Object[]{"!=", "key", 3}}
);
}
@Test
public void testAny() {
assertArrayEquals(any().toArray(), new Object[]{"any"});
assertArrayEquals(
any(eq("key", 2), neq("key", 3)).toArray(),
new Object[]{"any", new Object[]{"==", "key", 2}, new Object[]{"!=", "key", 3}}
);
}
@Test
public void testNone() {
assertArrayEquals(none().toArray(), new Object[]{"none"});
assertArrayEquals(
none(eq("key", 2), neq("key", 3)).toArray(),
new Object[]{"none", new Object[]{"==", "key", 2}, new Object[]{"!=", "key", 3}}
);
}
@Test
public void testHas() {
assertArrayEquals(has("key").toArray(), new Object[]{"has", "key"});
}
@Test
public void testHasNot() {
assertArrayEquals(notHas("key").toArray(), new Object[]{"!has", "key"});
}
@Test
public void testEq() {
assertArrayEquals(eq("key", 1).toArray(), new Object[]{"==", "key", 1});
}
@Test
public void testNeq() {
assertArrayEquals(neq("key", 1).toArray(), new Object[]{"!=", "key", 1});
}
@Test
public void testGt() {
assertArrayEquals(gt("key", 1).toArray(), new Object[]{">", "key", 1});
}
@Test
public void testGte() {
assertArrayEquals(gte("key", 1).toArray(), new Object[]{">=", "key", 1});
}
@Test
public void testLt() {
assertArrayEquals(lt("key", 1).toArray(), new Object[]{"<", "key", 1});
}
@Test
public void testLte() {
assertArrayEquals(lte("key", 1).toArray(), new Object[]{"<=", "key", 1});
}
@Test
public void testIn() {
assertArrayEquals(in("key", 1, 2, "Aap").toArray(), new Object[]{"in", "key", 1, 2, "Aap"});
}
@Test
public void testNotIn() {
assertArrayEquals(notIn("key", 1, 2, "Noot").toArray(), new Object[]{"!in", "key", 1, 2, "Noot"});
}
}

View File

@@ -27,11 +27,22 @@
'sources': [
'src/native_map_view.cpp',
'src/jni.cpp',
'src/java_types.cpp',
'src/attach_env.cpp',
'src/log_android.cpp',
'src/http_file_source.cpp',
'src/asset_file_source.cpp',
'src/thread.cpp',
'src/style/value.cpp',
'src/style/sources/sources.cpp',
'src/style/layers/layers.cpp',
'src/style/layers/layer.cpp',
'src/style/layers/background_layer.cpp',
'src/style/layers/circle_layer.cpp',
'src/style/layers/fill_layer.cpp',
'src/style/layers/line_layer.cpp',
'src/style/layers/raster_layer.cpp',
'src/style/layers/symbol_layer.cpp',
'../default/string_stdlib.cpp',
'../default/image.cpp',
'../default/png_reader.cpp',
@@ -50,6 +61,7 @@
'cflags_cc': [
'<@(boost_cflags)',
'<@(geojson_cflags)',
'<@(rapidjson_cflags)',
'<@(nunicode_cflags)',
'<@(sqlite_cflags)',
@@ -79,6 +91,7 @@
'<@(libpng_ldflags)',
'<@(libjpeg-turbo_static_libs)',
'<@(libjpeg-turbo_ldflags)',
'<@(geojson_static_libs)'
],
},
},

View File

@@ -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})
);

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
<% } -%>
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -0,0 +1,37 @@
#include "java_types.hpp"
namespace mbgl {
namespace android {
namespace java {
jni::jclass* ObjectArray::jclass;
jni::jclass* String::jclass;
jni::jclass* Boolean::jclass;
jni::jmethodID* Boolean::booleanValueMethodId;
jni::jclass* Number::jclass;
jni::jmethodID* Number::floatValueMethodId;
jni::jclass* Map::jclass;
jni::jmethodID* Map::getMethodId;
void registerNatives(JNIEnv& env) {
ObjectArray::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "[Ljava/lang/Object;")).release();
String::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/String")).release();
Boolean::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Boolean")).release();
Boolean::booleanValueMethodId = &jni::GetMethodID(env, *Boolean::jclass, "booleanValue", "()Z");
Number::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/lang/Number")).release();
Number::floatValueMethodId = &jni::GetMethodID(env, *Number::jclass, "floatValue", "()F");
Map::jclass = jni::NewGlobalRef(env, &jni::FindClass(env, "java/util/Map")).release();
Map::getMethodId = &jni::GetMethodID(env, *Map::jclass, "get", "(Ljava/lang/Object;)Ljava/lang/Object;");
}
}
}
}

View File

@@ -0,0 +1,35 @@
#pragma once
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
namespace java {
struct ObjectArray {
static jni::jclass* jclass;
};
struct String {
static jni::jclass* jclass;
};
struct Boolean {
static jni::jclass* jclass;
static jni::jmethodID* booleanValueMethodId;
};
struct Number {
static jni::jclass* jclass;
static jni::jmethodID* floatValueMethodId;
};
struct Map {
static jni::jclass* jclass;
static jni::jmethodID* getMethodId;
};
void registerNatives(JNIEnv&);
}
}
}

View File

@@ -9,11 +9,15 @@
#include <sys/system_properties.h>
#include "jni.hpp"
#include "java_types.hpp"
#include "native_map_view.hpp"
#include "style/layers/layers.hpp"
#include "style/sources/sources.hpp"
#include <mbgl/map/map.hpp>
#include <mbgl/map/camera.hpp>
#include <mbgl/annotation/annotation.hpp>
#include <mbgl/style/layer.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/platform/event.hpp>
@@ -1085,6 +1089,81 @@ void nativeRemoveCustomLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapView
nativeMapView->getMap().removeLayer(std_string_from_jstring(env, id));
}
jni::jobject* nativeGetLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* layerId) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeGetLayer");
assert(env);
assert(nativeMapViewPtr != 0);
//Get the native map peer
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
//Find the layer
mbgl::style::Layer* coreLayer = nativeMapView->getMap().getLayer(std_string_from_jstring(env, layerId));
if (!coreLayer) {
mbgl::Log::Debug(mbgl::Event::JNI, "No layer found");
return jni::Object<Layer>();
}
//Create and return the layer's native peer
return createJavaLayerPeer(*env, nativeMapView->getMap(), *coreLayer);
}
void nativeAddLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jlong nativeLayerPtr, jni::jstring* before) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddLayer");
assert(nativeMapViewPtr != 0);
assert(nativeLayerPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
Layer *layer = reinterpret_cast<Layer *>(nativeLayerPtr);
nativeMapView->getMap().addLayer(
layer->releaseCoreLayer(),
before ? mbgl::optional<std::string>(std_string_from_jstring(env, before)) : mbgl::optional<std::string>()
);
}
void nativeRemoveLayer(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveLayer");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
try {
nativeMapView->getMap().removeLayer(std_string_from_jstring(env, id));
} catch (const std::runtime_error& error) {
jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/layers/NoSuchLayerException"), error.what());
}
}
void nativeAddSource(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id, jni::jobject* jsource) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeAddSource");
assert(nativeMapViewPtr != 0);
assert(id != nullptr);
assert(jsource != nullptr);
//Convert
mbgl::optional<std::unique_ptr<mbgl::style::Source>> source = convertToNativeSource(
*env,
jni::Object<jni::jobject>(jsource), jni::String(id)
);
//Add to map view
if (source) {
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().addSource(std::move(*source));
}
}
void nativeRemoveSource(JNIEnv *env, jni::jobject* obj, jlong nativeMapViewPtr, jni::jstring* id) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeRemoveSource");
assert(nativeMapViewPtr != 0);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
try {
nativeMapView->getMap().removeSource(std_string_from_jstring(env, id));
} catch (const std::runtime_error& error) {
jni::ThrowNew(*env, jni::FindClass(*env, "com/mapbox/mapboxsdk/style/layers/NoSuchSourceException"), error.what());
}
}
// Offline calls begin
jlong createDefaultFileSource(JNIEnv *env, jni::jobject* obj, jni::jstring* cachePath_, jni::jstring* assetRoot_, jlong maximumCacheSize) {
@@ -1545,6 +1624,9 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
mbgl::android::RegisterNativeHTTPRequest(env);
java::registerNatives(env);
registerNativeLayers(env);
latLngClass = &jni::FindClass(env, "com/mapbox/mapboxsdk/geometry/LatLng");
latLngClass = jni::NewGlobalRef(env, latLngClass).release();
latLngConstructorId = &jni::GetMethodID(env, *latLngClass, "<init>", "(DD)V");
@@ -1699,6 +1781,11 @@ extern "C" JNIEXPORT jint JNI_OnLoad(JavaVM *vm, void *reserved) {
MAKE_NATIVE_METHOD(nativeFlyTo, "(JDDDJDD)V"),
MAKE_NATIVE_METHOD(nativeAddCustomLayer, "(JLcom/mapbox/mapboxsdk/layers/CustomLayer;Ljava/lang/String;)V"),
MAKE_NATIVE_METHOD(nativeRemoveCustomLayer, "(JLjava/lang/String;)V"),
MAKE_NATIVE_METHOD(nativeGetLayer, "(JLjava/lang/String;)Lcom/mapbox/mapboxsdk/style/layers/Layer;"),
MAKE_NATIVE_METHOD(nativeAddLayer, "(JJLjava/lang/String;)V"),
MAKE_NATIVE_METHOD(nativeRemoveLayer, "(JLjava/lang/String;)V"),
MAKE_NATIVE_METHOD(nativeAddSource, "(JLjava/lang/String;Lcom/mapbox/mapboxsdk/style/sources/Source;)V"),
MAKE_NATIVE_METHOD(nativeRemoveSource, "(JLjava/lang/String;)V"),
MAKE_NATIVE_METHOD(nativeSetContentPadding, "(JDDDD)V")
);

View File

@@ -0,0 +1,95 @@
#pragma once
#include "value.hpp"
#include <mbgl/platform/log.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/util/feature.hpp>
#include <mbgl/util/optional.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace style {
namespace conversion {
//XXX
#pragma GCC diagnostic ignored "-Wunused-parameter"
inline bool isUndefined(const mbgl::android::Value& value) {
return value.isNull();
}
inline bool isArray(const mbgl::android::Value& value) {
return value.isArray();
}
inline bool isObject(const mbgl::android::Value& value) {
return value.isObject();
}
inline std::size_t arrayLength(const mbgl::android::Value& value) {
return value.getLength();;
}
inline mbgl::android::Value arrayMember(const mbgl::android::Value& value, std::size_t i) {
return value.get(i);
}
inline optional<mbgl::android::Value> objectMember(const mbgl::android::Value& value, const char* key) {
mbgl::android::Value member = value.get(key);
if (!member.isNull()) {
return member;
} else {
return {};
}
}
template <class Fn>
optional<Error> eachMember(const mbgl::android::Value& value, Fn&& fn) {
//TODO
mbgl::Log::Warning(mbgl::Event::Android, "eachMember not implemented");
return {};
}
inline optional<bool> toBool(const mbgl::android::Value& value) {
if (value.isBool()) {
return value.toBool();
} else {
return {};
}
}
inline optional<float> toNumber(const mbgl::android::Value& value) {
if (value.isNumber()) {
return value.toNumber();
} else {
return {};
}
}
inline optional<std::string> toString(const mbgl::android::Value& value) {
if (value.isString()) {
return value.toString();
} else {
return {};
}
}
inline optional<Value> toValue(const mbgl::android::Value& value) {
if (value.isBool()) {
return { value.toBool() };
} else if (value.isString()) {
return { value.toString() };
} else if (value.isNumber()) {
return { value.toNumber() };
} else {
return {};
}
}
} // namespace conversion
} // namespace style
} // namespace mbgl

View File

@@ -0,0 +1,48 @@
#pragma once
#include "value.hpp"
#include <mapbox/geojson.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/geojson.hpp>
#include <mbgl/util/rapidjson.hpp>
#include <mbgl/platform/log.hpp>
#include <jni/jni.hpp>
#include <sstream>
#include <string>
namespace mbgl {
namespace style {
namespace conversion {
template <>
Result<GeoJSON> convertGeoJSON(const mbgl::android::Value& value) {
//Value should be a string wrapped in an object
mbgl::android::Value jsonValue = value.get("data");
if(value.isNull()) {
return Error { "no json data found" };
}
std::string jsonString = value.get("data").toString();
rapidjson::GenericDocument<rapidjson::UTF8<>, rapidjson::CrtAllocator> d;
d.Parse(jsonString.c_str());
if (d.HasParseError()) {
std::stringstream message;
message << d.GetErrorOffset() << " - " << rapidjson::GetParseError_En(d.GetParseError());
return Error { message.str() };
}
conversion::Result<GeoJSON> geoJSON = conversion::convertGeoJSON<JSValue>(d);
if (!geoJSON) {
return Error { geoJSON.error().message };
}
return geoJSON;
}
} // namespace conversion
} // namespace style
} // namespace mbgl

View File

@@ -0,0 +1,52 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
#include "background_layer.hpp"
#include <string>
//XXX
#include <mbgl/platform/log.hpp>
namespace mbgl {
namespace android {
BackgroundLayer::BackgroundLayer(jni::JNIEnv& env, jni::String layerId)
: Layer(env, std::make_unique<mbgl::style::BackgroundLayer>(jni::Make<std::string>(env, layerId))) {
mbgl::Log::Debug(mbgl::Event::JNI, "BackgroundLayer constructed, owning reference");
}
BackgroundLayer::BackgroundLayer(mbgl::Map& map, mbgl::style::BackgroundLayer& coreLayer)
: Layer(map, coreLayer) {
mbgl::Log::Debug(mbgl::Event::JNI, "BackgroundLayer Non-owning reference constructor");
}
BackgroundLayer::~BackgroundLayer() = default;
jni::Class<BackgroundLayer> BackgroundLayer::javaClass;
jni::jobject* BackgroundLayer::createJavaPeer(jni::JNIEnv& env) {
static auto constructor = BackgroundLayer::javaClass.template GetConstructor<jni::jlong>(env);
return BackgroundLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this));
}
void BackgroundLayer::registerNative(jni::JNIEnv& env) {
mbgl::Log::Debug(mbgl::Event::JNI, "Registering native background layer");
//Lookup the class
BackgroundLayer::javaClass = *jni::Class<BackgroundLayer>::Find(env).NewGlobalRef(env).release();
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
//Register the peer
jni::RegisterNativePeer<BackgroundLayer>(
env, BackgroundLayer::javaClass, "nativePtr",
std::make_unique<BackgroundLayer, JNIEnv&, jni::String>,
"initialize",
"finalize"
);
}
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,31 @@
// 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/background_layer.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class BackgroundLayer : public Layer {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/BackgroundLayer"; };
static jni::Class<BackgroundLayer> javaClass;
static void registerNative(jni::JNIEnv&);
BackgroundLayer(jni::JNIEnv&, jni::String);
BackgroundLayer(mbgl::Map&, mbgl::style::BackgroundLayer&);
~BackgroundLayer();
jni::jobject* createJavaPeer(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,52 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
#include "circle_layer.hpp"
#include <string>
//XXX
#include <mbgl/platform/log.hpp>
namespace mbgl {
namespace android {
CircleLayer::CircleLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId)
: Layer(env, std::make_unique<mbgl::style::CircleLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) {
mbgl::Log::Debug(mbgl::Event::JNI, "CircleLayer constructed, owning reference");
}
CircleLayer::CircleLayer(mbgl::Map& map, mbgl::style::CircleLayer& coreLayer)
: Layer(map, coreLayer) {
mbgl::Log::Debug(mbgl::Event::JNI, "CircleLayer Non-owning reference constructor");
}
CircleLayer::~CircleLayer() = default;
jni::Class<CircleLayer> CircleLayer::javaClass;
jni::jobject* CircleLayer::createJavaPeer(jni::JNIEnv& env) {
static auto constructor = CircleLayer::javaClass.template GetConstructor<jni::jlong>(env);
return CircleLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this));
}
void CircleLayer::registerNative(jni::JNIEnv& env) {
mbgl::Log::Debug(mbgl::Event::JNI, "Registering native background layer");
//Lookup the class
CircleLayer::javaClass = *jni::Class<CircleLayer>::Find(env).NewGlobalRef(env).release();
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
//Register the peer
jni::RegisterNativePeer<CircleLayer>(
env, CircleLayer::javaClass, "nativePtr",
std::make_unique<CircleLayer, JNIEnv&, jni::String, jni::String>,
"initialize",
"finalize"
);
}
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,31 @@
// 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/circle_layer.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class CircleLayer : public Layer {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/CircleLayer"; };
static jni::Class<CircleLayer> javaClass;
static void registerNative(jni::JNIEnv&);
CircleLayer(jni::JNIEnv&, jni::String, jni::String);
CircleLayer(mbgl::Map&, mbgl::style::CircleLayer&);
~CircleLayer();
jni::jobject* createJavaPeer(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,52 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
#include "fill_layer.hpp"
#include <string>
//XXX
#include <mbgl/platform/log.hpp>
namespace mbgl {
namespace android {
FillLayer::FillLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId)
: Layer(env, std::make_unique<mbgl::style::FillLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) {
mbgl::Log::Debug(mbgl::Event::JNI, "FillLayer constructed, owning reference");
}
FillLayer::FillLayer(mbgl::Map& map, mbgl::style::FillLayer& coreLayer)
: Layer(map, coreLayer) {
mbgl::Log::Debug(mbgl::Event::JNI, "FillLayer Non-owning reference constructor");
}
FillLayer::~FillLayer() = default;
jni::Class<FillLayer> FillLayer::javaClass;
jni::jobject* FillLayer::createJavaPeer(jni::JNIEnv& env) {
static auto constructor = FillLayer::javaClass.template GetConstructor<jni::jlong>(env);
return FillLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this));
}
void FillLayer::registerNative(jni::JNIEnv& env) {
mbgl::Log::Debug(mbgl::Event::JNI, "Registering native background layer");
//Lookup the class
FillLayer::javaClass = *jni::Class<FillLayer>::Find(env).NewGlobalRef(env).release();
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
//Register the peer
jni::RegisterNativePeer<FillLayer>(
env, FillLayer::javaClass, "nativePtr",
std::make_unique<FillLayer, JNIEnv&, jni::String, jni::String>,
"initialize",
"finalize"
);
}
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,31 @@
// 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/fill_layer.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class FillLayer : public Layer {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/FillLayer"; };
static jni::Class<FillLayer> javaClass;
static void registerNative(jni::JNIEnv&);
FillLayer(jni::JNIEnv&, jni::String, jni::String);
FillLayer(mbgl::Map&, mbgl::style::FillLayer&);
~FillLayer();
jni::jobject* createJavaPeer(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,158 @@
#include "layer.hpp"
#include "../android_conversion.hpp"
#include <jni/jni.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/layer.hpp>
#include <mbgl/style/conversion/source.hpp>
#include <string>
namespace mbgl {
namespace android {
/**
* Invoked when the construction is initiated from the jvm through a subclass
*/
Layer::Layer(jni::JNIEnv& env, std::unique_ptr<mbgl::style::Layer> coreLayer)
: ownedLayer(std::move(coreLayer))
, layer(*ownedLayer) {
mbgl::Log::Debug(mbgl::Event::JNI, "Layer constructed, owning reference");
}
Layer::Layer(mbgl::Map& coreMap, mbgl::style::Layer& coreLayer) : layer(coreLayer) , map(&coreMap) {
mbgl::Log::Debug(mbgl::Event::JNI, "Non-owning reference constructor");
}
Layer::~Layer() {
mbgl::Log::Debug(mbgl::Event::JNI, "Layer destroyed");
}
jni::String Layer::getId(jni::JNIEnv& env) {
return jni::Make<jni::String>(env, layer.getID());
}
std::unique_ptr<mbgl::style::Layer> Layer::releaseCoreLayer() {
assert(ownedLayer != nullptr);
return std::move(ownedLayer);
}
void Layer::setLayoutProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) {
mbgl::Log::Debug(mbgl::Event::JNI, "Set layout property");
Value value(env, jvalue);
//Convert and set property
optional<mbgl::style::conversion::Error> error = mbgl::style::conversion::setLayoutProperty(layer, jni::Make<std::string>(env, jname), value);
if (error) {
mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make<std::string>(env, jname) + " " + error->message);
return;
}
//Update the style if attached
if (ownedLayer == nullptr) {
map->update(mbgl::Update::RecalculateStyle);
}
}
void Layer::setPaintProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) {
mbgl::Log::Debug(mbgl::Event::JNI, "Set paint property");
Value value(env, jvalue);
//Convert and set property
optional<mbgl::style::conversion::Error> error = mbgl::style::conversion::setPaintProperty(layer, jni::Make<std::string>(env, jname), value, mbgl::optional<std::string>());
if (error) {
mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make<std::string>(env, jname) + " " + error->message);
return;
}
}
void Layer::updateStyle(jni::JNIEnv&, jni::jboolean updateClasses) {
mbgl::Log::Debug(mbgl::Event::JNI, "Update style property. Update classes: " + std::to_string(updateClasses));
//Update the style only if attached
if (ownedLayer == nullptr) {
Update flags = mbgl::Update::RecalculateStyle;
if(updateClasses) {
flags = flags | mbgl::Update::Classes;
}
map->update(flags);
} else {
mbgl::Log::Debug(mbgl::Event::JNI, "Not updating as layer is not attached to map (yet)");
}
}
void Layer::setFilter(jni::JNIEnv& env, jni::Array<jni::Object<>> jfilter) {
using namespace mbgl::style;
using namespace mbgl::style::conversion;
mbgl::Log::Debug(mbgl::Event::JNI, "Set filter");
Value wrapped(env, jfilter);
Filter filter;
Result<Filter> converted = convert<Filter>(wrapped);
if (!converted) {
mbgl::Log::Error(mbgl::Event::JNI, "Error setting filter: " + converted.error().message);
return;
}
filter = std::move(*converted);
if (layer.is<FillLayer>()) {
layer.as<FillLayer>()->setFilter(filter);
} else if (layer.is<LineLayer>()) {
layer.as<LineLayer>()->setFilter(filter);
} else if (layer.is<SymbolLayer>()) {
layer.as<SymbolLayer>()->setFilter(filter);
} else if (layer.is<CircleLayer>()) {
layer.as<CircleLayer>()->setFilter(filter);
} else {
mbgl::Log::Warning(mbgl::Event::JNI, "Layer doesn't support filters");
}
}
void Layer::setSourceLayer(jni::JNIEnv& env, jni::String sourceLayer) {
using namespace mbgl::style;
std::string layerId = jni::Make<std::string>(env, sourceLayer);
mbgl::Log::Debug(mbgl::Event::JNI, "Set source layer: " + layerId);
if (layer.is<FillLayer>()) {
layer.as<FillLayer>()->setSourceLayer(layerId);
} else if (layer.is<LineLayer>()) {
layer.as<LineLayer>()->setSourceLayer(layerId);
} else if (layer.is<SymbolLayer>()) {
layer.as<SymbolLayer>()->setSourceLayer(layerId);
} else if (layer.is<CircleLayer>()) {
layer.as<CircleLayer>()->setSourceLayer(layerId);
} else {
mbgl::Log::Warning(mbgl::Event::JNI, "Layer doesn't support source layer");
}
}
jni::Class<Layer> Layer::javaClass;
void Layer::registerNative(jni::JNIEnv& env) {
mbgl::Log::Debug(mbgl::Event::JNI, "Registering native base layer");
//Lookup the class
Layer::javaClass = *jni::Class<Layer>::Find(env).NewGlobalRef(env).release();
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
//Register the peer
jni::RegisterNativePeer<Layer>(env, Layer::javaClass, "nativePtr",
METHOD(&Layer::getId, "nativeGetId"),
METHOD(&Layer::setLayoutProperty, "nativeSetLayoutProperty"),
METHOD(&Layer::setPaintProperty, "nativeSetPaintProperty"),
METHOD(&Layer::updateStyle, "nativeUpdateStyle"),
METHOD(&Layer::setFilter, "nativeSetFilter"),
METHOD(&Layer::setSourceLayer, "nativeSetSourceLayer")
);
}
}
}

View File

@@ -0,0 +1,66 @@
#pragma once
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/map/map.hpp>
#include <mbgl/style/layer.hpp>
#include "../value.hpp"
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class Layer : private mbgl::util::noncopyable {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/Layer"; };
static jni::Class<Layer> javaClass;
static void registerNative(jni::JNIEnv&);
/*
* Called when a Java object is created on the c++ side
*/
Layer(mbgl::Map&, mbgl::style::Layer&);
/*
* Called when a Java object was created from the jvm side
*/
Layer(jni::JNIEnv&, std::unique_ptr<mbgl::style::Layer>);
virtual ~Layer();
virtual jni::jobject* createJavaPeer(jni::JNIEnv&) = 0;
jni::String getId(jni::JNIEnv&);
//Release the owned view and return it
std::unique_ptr<mbgl::style::Layer> releaseCoreLayer();
void setLayoutProperty(jni::JNIEnv&, jni::String, jni::Object<> value);
void setPaintProperty(jni::JNIEnv&, jni::String, jni::Object<> value);
void updateStyle(jni::JNIEnv&, jni::jboolean updateClasses);
/* common properties, but not shared by all */
void setFilter(jni::JNIEnv& env, jni::Array<jni::Object<>> jfilter);
void setSourceLayer(jni::JNIEnv& env, jni::String sourceLayer);
protected:
std::unique_ptr<mbgl::style::Layer> ownedLayer;
mbgl::style::Layer& layer;
mbgl::Map* map;
};
} //android
} //mbgl

View File

@@ -0,0 +1,60 @@
#include "layers.hpp"
#include <mbgl/style/layers/background_layer.hpp>
#include <mbgl/style/layers/circle_layer.hpp>
#include <mbgl/style/layers/fill_layer.hpp>
#include <mbgl/style/layers/line_layer.hpp>
#include <mbgl/style/layers/raster_layer.hpp>
#include <mbgl/style/layers/symbol_layer.hpp>
#include "background_layer.hpp"
#include "circle_layer.hpp"
#include "fill_layer.hpp"
#include "line_layer.hpp"
#include "raster_layer.hpp"
#include "symbol_layer.hpp"
namespace mbgl {
namespace android {
Layer* initializeLayerPeer(mbgl::Map& map, mbgl::style::Layer& coreLayer) {
Layer* layer;
if (coreLayer.is<mbgl::style::BackgroundLayer>()) {
layer = new BackgroundLayer(map, *coreLayer.as<mbgl::style::BackgroundLayer>());
} else if (coreLayer.is<mbgl::style::CircleLayer>()) {
layer = new CircleLayer(map, *coreLayer.as<mbgl::style::CircleLayer>());
} else if (coreLayer.is<mbgl::style::FillLayer>()) {
layer = new FillLayer(map, *coreLayer.as<mbgl::style::FillLayer>());
} else if (coreLayer.is<mbgl::style::LineLayer>()) {
layer = new LineLayer(map, *coreLayer.as<mbgl::style::LineLayer>());
} else if (coreLayer.is<mbgl::style::RasterLayer>()) {
layer = new RasterLayer(map, *coreLayer.as<mbgl::style::RasterLayer>());
} else if (coreLayer.is<mbgl::style::SymbolLayer>()) {
layer = new SymbolLayer(map, *coreLayer.as<mbgl::style::SymbolLayer>());
} else {
throw new std::runtime_error("Layer type not implemented");
}
return layer;
}
jni::jobject* createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, mbgl::style::Layer& coreLayer) {
std::unique_ptr<Layer> peerLayer = std::unique_ptr<Layer>(initializeLayerPeer(map, coreLayer));
jni::jobject* result = peerLayer->createJavaPeer(env);
peerLayer.release();
return result;
}
void registerNativeLayers(jni::JNIEnv& env) {
Layer::registerNative(env);
BackgroundLayer::registerNative(env);
CircleLayer::registerNative(env);
FillLayer::registerNative(env);
LineLayer::registerNative(env);
RasterLayer::registerNative(env);
SymbolLayer::registerNative(env);
}
}
}

View File

@@ -0,0 +1,20 @@
#pragma once
#include <mbgl/map/map.hpp>
#include <mbgl/style/layer.hpp>
#include "layer.hpp"
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
mbgl::android::Layer* initializeLayerPeer(mbgl::Map&, mbgl::style::Layer&);
jni::jobject* createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&);
void registerNativeLayers(jni::JNIEnv&);
}
}

View File

@@ -0,0 +1,52 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
#include "line_layer.hpp"
#include <string>
//XXX
#include <mbgl/platform/log.hpp>
namespace mbgl {
namespace android {
LineLayer::LineLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId)
: Layer(env, std::make_unique<mbgl::style::LineLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) {
mbgl::Log::Debug(mbgl::Event::JNI, "LineLayer constructed, owning reference");
}
LineLayer::LineLayer(mbgl::Map& map, mbgl::style::LineLayer& coreLayer)
: Layer(map, coreLayer) {
mbgl::Log::Debug(mbgl::Event::JNI, "LineLayer Non-owning reference constructor");
}
LineLayer::~LineLayer() = default;
jni::Class<LineLayer> LineLayer::javaClass;
jni::jobject* LineLayer::createJavaPeer(jni::JNIEnv& env) {
static auto constructor = LineLayer::javaClass.template GetConstructor<jni::jlong>(env);
return LineLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this));
}
void LineLayer::registerNative(jni::JNIEnv& env) {
mbgl::Log::Debug(mbgl::Event::JNI, "Registering native background layer");
//Lookup the class
LineLayer::javaClass = *jni::Class<LineLayer>::Find(env).NewGlobalRef(env).release();
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
//Register the peer
jni::RegisterNativePeer<LineLayer>(
env, LineLayer::javaClass, "nativePtr",
std::make_unique<LineLayer, JNIEnv&, jni::String, jni::String>,
"initialize",
"finalize"
);
}
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,31 @@
// 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/line_layer.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class LineLayer : public Layer {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/LineLayer"; };
static jni::Class<LineLayer> javaClass;
static void registerNative(jni::JNIEnv&);
LineLayer(jni::JNIEnv&, jni::String, jni::String);
LineLayer(mbgl::Map&, mbgl::style::LineLayer&);
~LineLayer();
jni::jobject* createJavaPeer(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,52 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
#include "raster_layer.hpp"
#include <string>
//XXX
#include <mbgl/platform/log.hpp>
namespace mbgl {
namespace android {
RasterLayer::RasterLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId)
: Layer(env, std::make_unique<mbgl::style::RasterLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) {
mbgl::Log::Debug(mbgl::Event::JNI, "RasterLayer constructed, owning reference");
}
RasterLayer::RasterLayer(mbgl::Map& map, mbgl::style::RasterLayer& coreLayer)
: Layer(map, coreLayer) {
mbgl::Log::Debug(mbgl::Event::JNI, "RasterLayer Non-owning reference constructor");
}
RasterLayer::~RasterLayer() = default;
jni::Class<RasterLayer> RasterLayer::javaClass;
jni::jobject* RasterLayer::createJavaPeer(jni::JNIEnv& env) {
static auto constructor = RasterLayer::javaClass.template GetConstructor<jni::jlong>(env);
return RasterLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this));
}
void RasterLayer::registerNative(jni::JNIEnv& env) {
mbgl::Log::Debug(mbgl::Event::JNI, "Registering native background layer");
//Lookup the class
RasterLayer::javaClass = *jni::Class<RasterLayer>::Find(env).NewGlobalRef(env).release();
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
//Register the peer
jni::RegisterNativePeer<RasterLayer>(
env, RasterLayer::javaClass, "nativePtr",
std::make_unique<RasterLayer, JNIEnv&, jni::String, jni::String>,
"initialize",
"finalize"
);
}
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,31 @@
// 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/raster_layer.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class RasterLayer : public Layer {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/RasterLayer"; };
static jni::Class<RasterLayer> javaClass;
static void registerNative(jni::JNIEnv&);
RasterLayer(jni::JNIEnv&, jni::String, jni::String);
RasterLayer(mbgl::Map&, mbgl::style::RasterLayer&);
~RasterLayer();
jni::jobject* createJavaPeer(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,52 @@
// This file is generated. Edit android/platform/scripts/generate-style-code.js, then run `make style-code-android`.
#include "symbol_layer.hpp"
#include <string>
//XXX
#include <mbgl/platform/log.hpp>
namespace mbgl {
namespace android {
SymbolLayer::SymbolLayer(jni::JNIEnv& env, jni::String layerId, jni::String sourceId)
: Layer(env, std::make_unique<mbgl::style::SymbolLayer>(jni::Make<std::string>(env, layerId), jni::Make<std::string>(env, sourceId))) {
mbgl::Log::Debug(mbgl::Event::JNI, "SymbolLayer constructed, owning reference");
}
SymbolLayer::SymbolLayer(mbgl::Map& map, mbgl::style::SymbolLayer& coreLayer)
: Layer(map, coreLayer) {
mbgl::Log::Debug(mbgl::Event::JNI, "SymbolLayer Non-owning reference constructor");
}
SymbolLayer::~SymbolLayer() = default;
jni::Class<SymbolLayer> SymbolLayer::javaClass;
jni::jobject* SymbolLayer::createJavaPeer(jni::JNIEnv& env) {
static auto constructor = SymbolLayer::javaClass.template GetConstructor<jni::jlong>(env);
return SymbolLayer::javaClass.New(env, constructor, reinterpret_cast<jni::jlong>(this));
}
void SymbolLayer::registerNative(jni::JNIEnv& env) {
mbgl::Log::Debug(mbgl::Event::JNI, "Registering native background layer");
//Lookup the class
SymbolLayer::javaClass = *jni::Class<SymbolLayer>::Find(env).NewGlobalRef(env).release();
#define METHOD(MethodPtr, name) jni::MakeNativePeerMethod<decltype(MethodPtr), (MethodPtr)>(name)
//Register the peer
jni::RegisterNativePeer<SymbolLayer>(
env, SymbolLayer::javaClass, "nativePtr",
std::make_unique<SymbolLayer, JNIEnv&, jni::String, jni::String>,
"initialize",
"finalize"
);
}
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,31 @@
// 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/symbol_layer.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
class SymbolLayer : public Layer {
public:
static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/SymbolLayer"; };
static jni::Class<SymbolLayer> javaClass;
static void registerNative(jni::JNIEnv&);
SymbolLayer(jni::JNIEnv&, jni::String, jni::String);
SymbolLayer(mbgl::Map&, mbgl::style::SymbolLayer&);
~SymbolLayer();
jni::jobject* createJavaPeer(jni::JNIEnv&);
};
} // namespace android
} // namespace mbgl

View File

@@ -0,0 +1,28 @@
#include "sources.hpp"
#include "../value.hpp"
#include "../android_conversion.hpp"
#include "../android_geojson.hpp"
#include <mbgl/util/constants.hpp>
#include <mbgl/style/conversion.hpp>
#include <mbgl/style/conversion/source.hpp>
#include <string>
namespace mbgl {
namespace android {
mbgl::optional<std::unique_ptr<mbgl::style::Source>> convertToNativeSource(jni::JNIEnv& env, jni::Object<jni::jobject> jvalue, jni::String id) {
using namespace mbgl::style;
Value value(env, jvalue);
conversion::Result<std::unique_ptr<Source>> source = conversion::convert<std::unique_ptr<Source>>(value, jni::Make<std::string>(env, id));
if (!source) {
mbgl::Log::Error(mbgl::Event::JNI, "Unable to add source: " + source.error().message);
return {};
}
return std::move(*source);
}
}
}

View File

@@ -0,0 +1,14 @@
#pragma once
#include <mbgl/style/source.hpp>
#include <mbgl/util/optional.hpp>
#include <jni/jni.hpp>
namespace mbgl {
namespace android {
mbgl::optional<std::unique_ptr<mbgl::style::Source>> convertToNativeSource(jni::JNIEnv& env, jni::Object<jni::jobject> jsource, jni::String id);
}
}

View File

@@ -0,0 +1,67 @@
#include "value.hpp"
#include "../java_types.hpp"
namespace mbgl {
namespace android {
//Instance
Value::Value(jni::JNIEnv& env, jni::jobject* _value) : jenv(env), value(_value) {}
Value::~Value() {}
bool Value::isNull() const {
return value == nullptr;
}
bool Value::isArray() const {
return jni::IsInstanceOf(jenv, value, *java::ObjectArray::jclass);
}
bool Value::isObject() const {
return jni::IsInstanceOf(jenv, value, *java::Map::jclass);;
}
bool Value::isString() const {
return jni::IsInstanceOf(jenv, value, *java::String::jclass);
}
bool Value::isBool() const {
return jni::IsInstanceOf(jenv, value, *java::Boolean::jclass);
}
bool Value::isNumber() const {
return jni::IsInstanceOf(jenv, value, *java::Number::jclass);
}
std::string Value::toString() const {
jni::jstring* string = reinterpret_cast<jni::jstring*>(value);
return jni::Make<std::string>(jenv, jni::String(string));
}
float Value::toNumber() const {
return jni::CallMethod<jni::jfloat>(jenv, value, *java::Number::floatValueMethodId);
}
bool Value::toBool() const {
return jni::CallMethod<jni::jboolean>(jenv, value, *java::Boolean::booleanValueMethodId);
}
Value Value::get(const char* key) const {
jni::jobject* member = jni::CallMethod<jni::jobject*>(jenv, value, *java::Map::getMethodId, jni::Make<jni::String>(jenv, std::string(key)).Get());
return Value(jenv, member);
}
int Value::getLength() const {
auto array = (jni::jarray<jni::jobject>*) value;
return jni::GetArrayLength(jenv, *array);
}
Value Value::get(const int index ) const {
auto array = (jni::jarray<jni::jobject>*) value;
return Value(jenv, jni::GetObjectArrayElement(jenv, *array, index));
}
}
}

View File

@@ -0,0 +1,35 @@
#pragma once
#include <jni/jni.hpp>
#include <string>
namespace mbgl {
namespace android {
class Value {
public:
Value(jni::JNIEnv&, jni::jobject*);
virtual ~Value();
bool isNull() const;
bool isArray() const;
bool isObject() const;
bool isString() const;
bool isBool() const;
bool isNumber() const;
std::string toString() const;
float toNumber() const;
bool toBool() const;
Value get(const char* key) const;
int getLength() const;
Value get(const int index ) const;
jni::JNIEnv& jenv;
jni::jobject* value;
};
}
}