From 80ec05cf47feb9f225d46222980d6942b9a4038f Mon Sep 17 00:00:00 2001 From: Mikhail Pozdnyakov Date: Tue, 6 Nov 2018 11:25:09 +0200 Subject: [core][android] Implement LayerManager for Android The newly introduced `LayerManagerAndroid` is now responsible for creating both style layer objects and their java peers on Android. --- platform/android/src/jni.cpp | 2 +- platform/android/src/native_map_view.cpp | 8 +- .../android/src/style/layers/background_layer.cpp | 30 ++++- .../android/src/style/layers/background_layer.hpp | 17 ++- platform/android/src/style/layers/circle_layer.cpp | 30 ++++- platform/android/src/style/layers/circle_layer.hpp | 17 ++- platform/android/src/style/layers/custom_layer.cpp | 26 +++-- platform/android/src/style/layers/custom_layer.hpp | 14 +++ .../src/style/layers/fill_extrusion_layer.cpp | 30 ++++- .../src/style/layers/fill_extrusion_layer.hpp | 17 ++- platform/android/src/style/layers/fill_layer.cpp | 30 ++++- platform/android/src/style/layers/fill_layer.hpp | 17 ++- .../android/src/style/layers/heatmap_layer.cpp | 30 ++++- .../android/src/style/layers/heatmap_layer.hpp | 17 ++- .../android/src/style/layers/hillshade_layer.cpp | 30 ++++- .../android/src/style/layers/hillshade_layer.hpp | 17 ++- platform/android/src/style/layers/layer.cpp | 2 +- platform/android/src/style/layers/layer.cpp.ejs | 32 ++++-- platform/android/src/style/layers/layer.hpp | 66 +++++++---- platform/android/src/style/layers/layer.hpp.ejs | 17 ++- platform/android/src/style/layers/layers.cpp | 126 +++++++++++---------- platform/android/src/style/layers/layers.hpp | 31 +++-- platform/android/src/style/layers/line_layer.cpp | 30 ++++- platform/android/src/style/layers/line_layer.hpp | 17 ++- platform/android/src/style/layers/raster_layer.cpp | 30 ++++- platform/android/src/style/layers/raster_layer.hpp | 17 ++- platform/android/src/style/layers/symbol_layer.cpp | 30 ++++- platform/android/src/style/layers/symbol_layer.hpp | 17 ++- .../android/src/style/layers/unknown_layer.cpp | 4 +- .../android/src/style/layers/unknown_layer.hpp | 2 +- 30 files changed, 560 insertions(+), 193 deletions(-) diff --git a/platform/android/src/jni.cpp b/platform/android/src/jni.cpp index bb28bf6ea4..4e9cc2af07 100755 --- a/platform/android/src/jni.cpp +++ b/platform/android/src/jni.cpp @@ -160,7 +160,7 @@ void registerNatives(JavaVM *vm) { // Style TransitionOptions::registerNative(env); - registerNativeLayers(env); + LayerManagerAndroid::get()->registerNative(env); Source::registerNative(env); Light::registerNative(env); Position::registerNative(env); diff --git a/platform/android/src/native_map_view.cpp b/platform/android/src/native_map_view.cpp index f12c48f938..1c744a6b57 100755 --- a/platform/android/src/native_map_view.cpp +++ b/platform/android/src/native_map_view.cpp @@ -733,7 +733,7 @@ jni::Local>> NativeMapView::getLayers(JNIEnv& env) auto jLayers = jni::Array>::New(env, layers.size()); int index = 0; for (auto layer : layers) { - jLayers.Set(env, index, createJavaLayerPeer(env, *map, *layer)); + jLayers.Set(env, index, LayerManagerAndroid::get()->createJavaLayerPeer(env, *map, *layer)); index++; } @@ -750,7 +750,7 @@ jni::Local> NativeMapView::getLayer(JNIEnv& env, const jni::S } // Create and return the layer's native peer - return createJavaLayerPeer(env, *map, *coreLayer); + return LayerManagerAndroid::get()->createJavaLayerPeer(env, *map, *coreLayer); } void NativeMapView::addLayer(JNIEnv& env, jlong nativeLayerPtr, const jni::String& before) { @@ -830,7 +830,7 @@ void NativeMapView::addLayerAt(JNIEnv& env, jlong nativeLayerPtr, jni::jint inde jni::Local> NativeMapView::removeLayerById(JNIEnv& env, const jni::String& id) { std::unique_ptr coreLayer = map->getStyle().removeLayer(jni::Make(env, id)); if (coreLayer) { - return createJavaLayerPeer(env, *map, std::move(coreLayer)); + return LayerManagerAndroid::get()->createJavaLayerPeer(env, *map, std::move(coreLayer)); } else { return jni::Local>(); } @@ -851,7 +851,7 @@ jni::Local> NativeMapView::removeLayerAt(JNIEnv& env, jni::ji std::unique_ptr coreLayer = map->getStyle().removeLayer(layers.at(index)->getID()); if (coreLayer) { - return createJavaLayerPeer(env, *map, std::move(coreLayer)); + return LayerManagerAndroid::get()->createJavaLayerPeer(env, *map, std::move(coreLayer)); } else { return jni::Local>(); } diff --git a/platform/android/src/style/layers/background_layer.cpp b/platform/android/src/style/layers/background_layer.cpp index 45ec9380d0..c0d3f39bc4 100644 --- a/platform/android/src/style/layers/background_layer.cpp +++ b/platform/android/src/style/layers/background_layer.cpp @@ -7,6 +7,8 @@ #include "../conversion/property_value.hpp" #include "../conversion/transition_options.hpp" +#include + namespace mbgl { namespace android { @@ -18,7 +20,7 @@ namespace android { * Creates an owning peer object (for layers not attached to the map) from the JVM side */ BackgroundLayer::BackgroundLayer(jni::JNIEnv& env, jni::String& layerId) - : Layer(env, std::make_unique(jni::Make(env, layerId))) { + : Layer(std::make_unique(jni::Make(env, layerId))) { } /** @@ -94,13 +96,29 @@ namespace android { } - jni::Local> BackgroundLayer::createJavaPeer(jni::JNIEnv& env) { - static auto& javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - return javaClass.New(env, constructor, reinterpret_cast(this)); + // BackgroundJavaLayerPeerFactory + + BackgroundJavaLayerPeerFactory::~BackgroundJavaLayerPeerFactory() = default; + + namespace { + jni::Local> createJavaPeer(jni::JNIEnv& env, Layer* layer) { + static auto& javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(layer)); + } + } // namespace + + jni::Local> BackgroundJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, mbgl::style::Layer& layer) { + assert(layer.baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new BackgroundLayer(map, toBackgroundLayer(layer))); + } + + jni::Local> BackgroundJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr layer) { + assert(layer->baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new BackgroundLayer(map, std::unique_ptr(static_cast(layer.release())))); } - void BackgroundLayer::registerNative(jni::JNIEnv& env) { + void BackgroundJavaLayerPeerFactory::registerNative(jni::JNIEnv& env) { // Lookup the class static auto& javaClass = jni::Class::Singleton(env); diff --git a/platform/android/src/style/layers/background_layer.hpp b/platform/android/src/style/layers/background_layer.hpp index 78cd5659fd..efe882d531 100644 --- a/platform/android/src/style/layers/background_layer.hpp +++ b/platform/android/src/style/layers/background_layer.hpp @@ -15,8 +15,6 @@ public: using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/BackgroundLayer"; }; - static void registerNative(jni::JNIEnv&); - BackgroundLayer(jni::JNIEnv&, jni::String&); BackgroundLayer(mbgl::Map&, mbgl::style::BackgroundLayer&); @@ -38,9 +36,22 @@ public: jni::Local> getBackgroundOpacity(jni::JNIEnv&); void setBackgroundOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); jni::Local> getBackgroundOpacityTransition(jni::JNIEnv&); - jni::Local> createJavaPeer(jni::JNIEnv&); }; // class BackgroundLayer +class BackgroundJavaLayerPeerFactory final : public JavaLayerPeerFactory, public mbgl::style::BackgroundLayerFactory { +public: + ~BackgroundJavaLayerPeerFactory() override; + + // JavaLayerPeerFactory overrides. + jni::Local> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&) final; + jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr) final; + + void registerNative(jni::JNIEnv&) final; + + style::LayerFactory* getLayerFactory() final { return this; } + +}; // class BackgroundJavaLayerPeerFactory + } // namespace android } // namespace mbgl diff --git a/platform/android/src/style/layers/circle_layer.cpp b/platform/android/src/style/layers/circle_layer.cpp index 1b5b7649f0..13f3a4cb03 100644 --- a/platform/android/src/style/layers/circle_layer.cpp +++ b/platform/android/src/style/layers/circle_layer.cpp @@ -7,6 +7,8 @@ #include "../conversion/property_value.hpp" #include "../conversion/transition_options.hpp" +#include + namespace mbgl { namespace android { @@ -18,7 +20,7 @@ namespace android { * Creates an owning peer object (for layers not attached to the map) from the JVM side */ CircleLayer::CircleLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) - : Layer(env, std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { + : Layer(std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { } /** @@ -199,13 +201,29 @@ namespace android { } - jni::Local> CircleLayer::createJavaPeer(jni::JNIEnv& env) { - static auto& javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - return javaClass.New(env, constructor, reinterpret_cast(this)); + // CircleJavaLayerPeerFactory + + CircleJavaLayerPeerFactory::~CircleJavaLayerPeerFactory() = default; + + namespace { + jni::Local> createJavaPeer(jni::JNIEnv& env, Layer* layer) { + static auto& javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(layer)); + } + } // namespace + + jni::Local> CircleJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, mbgl::style::Layer& layer) { + assert(layer.baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new CircleLayer(map, toCircleLayer(layer))); + } + + jni::Local> CircleJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr layer) { + assert(layer->baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new CircleLayer(map, std::unique_ptr(static_cast(layer.release())))); } - void CircleLayer::registerNative(jni::JNIEnv& env) { + void CircleJavaLayerPeerFactory::registerNative(jni::JNIEnv& env) { // Lookup the class static auto& javaClass = jni::Class::Singleton(env); diff --git a/platform/android/src/style/layers/circle_layer.hpp b/platform/android/src/style/layers/circle_layer.hpp index 0ff34094e1..5c53f6c191 100644 --- a/platform/android/src/style/layers/circle_layer.hpp +++ b/platform/android/src/style/layers/circle_layer.hpp @@ -15,8 +15,6 @@ public: using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/CircleLayer"; }; - static void registerNative(jni::JNIEnv&); - CircleLayer(jni::JNIEnv&, jni::String&, jni::String&); CircleLayer(mbgl::Map&, mbgl::style::CircleLayer&); @@ -64,9 +62,22 @@ public: jni::Local> getCircleStrokeOpacity(jni::JNIEnv&); void setCircleStrokeOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); jni::Local> getCircleStrokeOpacityTransition(jni::JNIEnv&); - jni::Local> createJavaPeer(jni::JNIEnv&); }; // class CircleLayer +class CircleJavaLayerPeerFactory final : public JavaLayerPeerFactory, public mbgl::style::CircleLayerFactory { +public: + ~CircleJavaLayerPeerFactory() override; + + // JavaLayerPeerFactory overrides. + jni::Local> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&) final; + jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr) final; + + void registerNative(jni::JNIEnv&) final; + + style::LayerFactory* getLayerFactory() final { return this; } + +}; // class CircleJavaLayerPeerFactory + } // namespace android } // namespace mbgl diff --git a/platform/android/src/style/layers/custom_layer.cpp b/platform/android/src/style/layers/custom_layer.cpp index f6f3bb249c..3f44aa8505 100644 --- a/platform/android/src/style/layers/custom_layer.cpp +++ b/platform/android/src/style/layers/custom_layer.cpp @@ -8,7 +8,7 @@ namespace mbgl { namespace android { CustomLayer::CustomLayer(jni::JNIEnv& env, const jni::String& layerId, jni::jlong host) - : Layer(env, std::make_unique( + : Layer(std::make_unique( jni::Make(env, layerId), std::unique_ptr(reinterpret_cast(host))) ) { @@ -19,7 +19,7 @@ namespace android { } CustomLayer::CustomLayer(mbgl::Map& map, std::unique_ptr coreLayer) - : Layer(map, std::move(coreLayer)) { + : Layer(map, std::move(coreLayer)) { } CustomLayer::~CustomLayer() = default; @@ -33,13 +33,25 @@ namespace android { } } - jni::Local> CustomLayer::createJavaPeer(jni::JNIEnv& env) { - static auto& javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - return javaClass.New(env, constructor, reinterpret_cast(this)); + namespace { + jni::Local> createJavaPeer(jni::JNIEnv& env, Layer* layer) { + static auto& javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(layer)); + } + } + + CustomJavaLayerPeerFactory::~CustomJavaLayerPeerFactory() = default; + + jni::Local> CustomJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, mbgl::style::Layer& layer) { + return createJavaPeer(env, new CustomLayer(map, static_cast(layer))); + } + + jni::Local> CustomJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr layer) { + return createJavaPeer(env, new CustomLayer(map, std::unique_ptr(static_cast(layer.release())))); } - void CustomLayer::registerNative(jni::JNIEnv& env) { + void CustomJavaLayerPeerFactory::registerNative(jni::JNIEnv& env) { // Lookup the class static auto& javaClass = jni::Class::Singleton(env); diff --git a/platform/android/src/style/layers/custom_layer.hpp b/platform/android/src/style/layers/custom_layer.hpp index 950fcef9c1..ea4a3d79a5 100644 --- a/platform/android/src/style/layers/custom_layer.hpp +++ b/platform/android/src/style/layers/custom_layer.hpp @@ -25,5 +25,19 @@ public: }; // class CustomLayer +class CustomJavaLayerPeerFactory final : public JavaLayerPeerFactory, public mbgl::style::CustomLayerFactory { +public: + ~CustomJavaLayerPeerFactory() override; + + // JavaLayerPeerFactory overrides. + jni::Local> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&) final; + jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr) final; + + void registerNative(jni::JNIEnv&) final; + + style::LayerFactory* getLayerFactory() final { return this; } + +}; // class CustomJavaLayerPeerFactory + } // namespace android } // namespace mbgl diff --git a/platform/android/src/style/layers/fill_extrusion_layer.cpp b/platform/android/src/style/layers/fill_extrusion_layer.cpp index b047f08dc0..fd67b391ac 100644 --- a/platform/android/src/style/layers/fill_extrusion_layer.cpp +++ b/platform/android/src/style/layers/fill_extrusion_layer.cpp @@ -7,6 +7,8 @@ #include "../conversion/property_value.hpp" #include "../conversion/transition_options.hpp" +#include + namespace mbgl { namespace android { @@ -18,7 +20,7 @@ namespace android { * Creates an owning peer object (for layers not attached to the map) from the JVM side */ FillExtrusionLayer::FillExtrusionLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) - : Layer(env, std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { + : Layer(std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { } /** @@ -153,13 +155,29 @@ namespace android { } - jni::Local> FillExtrusionLayer::createJavaPeer(jni::JNIEnv& env) { - static auto& javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - return javaClass.New(env, constructor, reinterpret_cast(this)); + // FillExtrusionJavaLayerPeerFactory + + FillExtrusionJavaLayerPeerFactory::~FillExtrusionJavaLayerPeerFactory() = default; + + namespace { + jni::Local> createJavaPeer(jni::JNIEnv& env, Layer* layer) { + static auto& javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(layer)); + } + } // namespace + + jni::Local> FillExtrusionJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, mbgl::style::Layer& layer) { + assert(layer.baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new FillExtrusionLayer(map, toFillExtrusionLayer(layer))); + } + + jni::Local> FillExtrusionJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr layer) { + assert(layer->baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new FillExtrusionLayer(map, std::unique_ptr(static_cast(layer.release())))); } - void FillExtrusionLayer::registerNative(jni::JNIEnv& env) { + void FillExtrusionJavaLayerPeerFactory::registerNative(jni::JNIEnv& env) { // Lookup the class static auto& javaClass = jni::Class::Singleton(env); diff --git a/platform/android/src/style/layers/fill_extrusion_layer.hpp b/platform/android/src/style/layers/fill_extrusion_layer.hpp index abc30b5845..ace8cd1357 100644 --- a/platform/android/src/style/layers/fill_extrusion_layer.hpp +++ b/platform/android/src/style/layers/fill_extrusion_layer.hpp @@ -15,8 +15,6 @@ public: using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/FillExtrusionLayer"; }; - static void registerNative(jni::JNIEnv&); - FillExtrusionLayer(jni::JNIEnv&, jni::String&, jni::String&); FillExtrusionLayer(mbgl::Map&, mbgl::style::FillExtrusionLayer&); @@ -52,9 +50,22 @@ public: jni::Local> getFillExtrusionBase(jni::JNIEnv&); void setFillExtrusionBaseTransition(jni::JNIEnv&, jlong duration, jlong delay); jni::Local> getFillExtrusionBaseTransition(jni::JNIEnv&); - jni::Local> createJavaPeer(jni::JNIEnv&); }; // class FillExtrusionLayer +class FillExtrusionJavaLayerPeerFactory final : public JavaLayerPeerFactory, public mbgl::style::FillExtrusionLayerFactory { +public: + ~FillExtrusionJavaLayerPeerFactory() override; + + // JavaLayerPeerFactory overrides. + jni::Local> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&) final; + jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr) final; + + void registerNative(jni::JNIEnv&) final; + + style::LayerFactory* getLayerFactory() final { return this; } + +}; // class FillExtrusionJavaLayerPeerFactory + } // namespace android } // namespace mbgl diff --git a/platform/android/src/style/layers/fill_layer.cpp b/platform/android/src/style/layers/fill_layer.cpp index 411895488f..252771038a 100644 --- a/platform/android/src/style/layers/fill_layer.cpp +++ b/platform/android/src/style/layers/fill_layer.cpp @@ -7,6 +7,8 @@ #include "../conversion/property_value.hpp" #include "../conversion/transition_options.hpp" +#include + namespace mbgl { namespace android { @@ -18,7 +20,7 @@ namespace android { * Creates an owning peer object (for layers not attached to the map) from the JVM side */ FillLayer::FillLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) - : Layer(env, std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { + : Layer(std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { } /** @@ -140,13 +142,29 @@ namespace android { } - jni::Local> FillLayer::createJavaPeer(jni::JNIEnv& env) { - static auto& javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - return javaClass.New(env, constructor, reinterpret_cast(this)); + // FillJavaLayerPeerFactory + + FillJavaLayerPeerFactory::~FillJavaLayerPeerFactory() = default; + + namespace { + jni::Local> createJavaPeer(jni::JNIEnv& env, Layer* layer) { + static auto& javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(layer)); + } + } // namespace + + jni::Local> FillJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, mbgl::style::Layer& layer) { + assert(layer.baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new FillLayer(map, toFillLayer(layer))); + } + + jni::Local> FillJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr layer) { + assert(layer->baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new FillLayer(map, std::unique_ptr(static_cast(layer.release())))); } - void FillLayer::registerNative(jni::JNIEnv& env) { + void FillJavaLayerPeerFactory::registerNative(jni::JNIEnv& env) { // Lookup the class static auto& javaClass = jni::Class::Singleton(env); diff --git a/platform/android/src/style/layers/fill_layer.hpp b/platform/android/src/style/layers/fill_layer.hpp index ea96320570..c7b469ac90 100644 --- a/platform/android/src/style/layers/fill_layer.hpp +++ b/platform/android/src/style/layers/fill_layer.hpp @@ -15,8 +15,6 @@ public: using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/FillLayer"; }; - static void registerNative(jni::JNIEnv&); - FillLayer(jni::JNIEnv&, jni::String&, jni::String&); FillLayer(mbgl::Map&, mbgl::style::FillLayer&); @@ -50,9 +48,22 @@ public: jni::Local> getFillPattern(jni::JNIEnv&); void setFillPatternTransition(jni::JNIEnv&, jlong duration, jlong delay); jni::Local> getFillPatternTransition(jni::JNIEnv&); - jni::Local> createJavaPeer(jni::JNIEnv&); }; // class FillLayer +class FillJavaLayerPeerFactory final : public JavaLayerPeerFactory, public mbgl::style::FillLayerFactory { +public: + ~FillJavaLayerPeerFactory() override; + + // JavaLayerPeerFactory overrides. + jni::Local> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&) final; + jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr) final; + + void registerNative(jni::JNIEnv&) final; + + style::LayerFactory* getLayerFactory() final { return this; } + +}; // class FillJavaLayerPeerFactory + } // namespace android } // namespace mbgl diff --git a/platform/android/src/style/layers/heatmap_layer.cpp b/platform/android/src/style/layers/heatmap_layer.cpp index 5a0114d52a..d478746f09 100644 --- a/platform/android/src/style/layers/heatmap_layer.cpp +++ b/platform/android/src/style/layers/heatmap_layer.cpp @@ -7,6 +7,8 @@ #include "../conversion/property_value.hpp" #include "../conversion/transition_options.hpp" +#include + namespace mbgl { namespace android { @@ -18,7 +20,7 @@ namespace android { * Creates an owning peer object (for layers not attached to the map) from the JVM side */ HeatmapLayer::HeatmapLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) - : Layer(env, std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { + : Layer(std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { } /** @@ -108,13 +110,29 @@ namespace android { } - jni::Local> HeatmapLayer::createJavaPeer(jni::JNIEnv& env) { - static auto& javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - return javaClass.New(env, constructor, reinterpret_cast(this)); + // HeatmapJavaLayerPeerFactory + + HeatmapJavaLayerPeerFactory::~HeatmapJavaLayerPeerFactory() = default; + + namespace { + jni::Local> createJavaPeer(jni::JNIEnv& env, Layer* layer) { + static auto& javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(layer)); + } + } // namespace + + jni::Local> HeatmapJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, mbgl::style::Layer& layer) { + assert(layer.baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new HeatmapLayer(map, toHeatmapLayer(layer))); + } + + jni::Local> HeatmapJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr layer) { + assert(layer->baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new HeatmapLayer(map, std::unique_ptr(static_cast(layer.release())))); } - void HeatmapLayer::registerNative(jni::JNIEnv& env) { + void HeatmapJavaLayerPeerFactory::registerNative(jni::JNIEnv& env) { // Lookup the class static auto& javaClass = jni::Class::Singleton(env); diff --git a/platform/android/src/style/layers/heatmap_layer.hpp b/platform/android/src/style/layers/heatmap_layer.hpp index 2976e6c482..45c194b0f0 100644 --- a/platform/android/src/style/layers/heatmap_layer.hpp +++ b/platform/android/src/style/layers/heatmap_layer.hpp @@ -15,8 +15,6 @@ public: using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/HeatmapLayer"; }; - static void registerNative(jni::JNIEnv&); - HeatmapLayer(jni::JNIEnv&, jni::String&, jni::String&); HeatmapLayer(mbgl::Map&, mbgl::style::HeatmapLayer&); @@ -42,9 +40,22 @@ public: jni::Local> getHeatmapOpacity(jni::JNIEnv&); void setHeatmapOpacityTransition(jni::JNIEnv&, jlong duration, jlong delay); jni::Local> getHeatmapOpacityTransition(jni::JNIEnv&); - jni::Local> createJavaPeer(jni::JNIEnv&); }; // class HeatmapLayer +class HeatmapJavaLayerPeerFactory final : public JavaLayerPeerFactory, public mbgl::style::HeatmapLayerFactory { +public: + ~HeatmapJavaLayerPeerFactory() override; + + // JavaLayerPeerFactory overrides. + jni::Local> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&) final; + jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr) final; + + void registerNative(jni::JNIEnv&) final; + + style::LayerFactory* getLayerFactory() final { return this; } + +}; // class HeatmapJavaLayerPeerFactory + } // namespace android } // namespace mbgl diff --git a/platform/android/src/style/layers/hillshade_layer.cpp b/platform/android/src/style/layers/hillshade_layer.cpp index 3f3c8e311a..3c2ab33d43 100644 --- a/platform/android/src/style/layers/hillshade_layer.cpp +++ b/platform/android/src/style/layers/hillshade_layer.cpp @@ -7,6 +7,8 @@ #include "../conversion/property_value.hpp" #include "../conversion/transition_options.hpp" +#include + namespace mbgl { namespace android { @@ -18,7 +20,7 @@ namespace android { * Creates an owning peer object (for layers not attached to the map) from the JVM side */ HillshadeLayer::HillshadeLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) - : Layer(env, std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { + : Layer(std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { } /** @@ -122,13 +124,29 @@ namespace android { } - jni::Local> HillshadeLayer::createJavaPeer(jni::JNIEnv& env) { - static auto& javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - return javaClass.New(env, constructor, reinterpret_cast(this)); + // HillshadeJavaLayerPeerFactory + + HillshadeJavaLayerPeerFactory::~HillshadeJavaLayerPeerFactory() = default; + + namespace { + jni::Local> createJavaPeer(jni::JNIEnv& env, Layer* layer) { + static auto& javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(layer)); + } + } // namespace + + jni::Local> HillshadeJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, mbgl::style::Layer& layer) { + assert(layer.baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new HillshadeLayer(map, toHillshadeLayer(layer))); + } + + jni::Local> HillshadeJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr layer) { + assert(layer->baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new HillshadeLayer(map, std::unique_ptr(static_cast(layer.release())))); } - void HillshadeLayer::registerNative(jni::JNIEnv& env) { + void HillshadeJavaLayerPeerFactory::registerNative(jni::JNIEnv& env) { // Lookup the class static auto& javaClass = jni::Class::Singleton(env); diff --git a/platform/android/src/style/layers/hillshade_layer.hpp b/platform/android/src/style/layers/hillshade_layer.hpp index 9ca0e33cfd..db0ea736b4 100644 --- a/platform/android/src/style/layers/hillshade_layer.hpp +++ b/platform/android/src/style/layers/hillshade_layer.hpp @@ -15,8 +15,6 @@ public: using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/HillshadeLayer"; }; - static void registerNative(jni::JNIEnv&); - HillshadeLayer(jni::JNIEnv&, jni::String&, jni::String&); HillshadeLayer(mbgl::Map&, mbgl::style::HillshadeLayer&); @@ -46,9 +44,22 @@ public: jni::Local> getHillshadeAccentColor(jni::JNIEnv&); void setHillshadeAccentColorTransition(jni::JNIEnv&, jlong duration, jlong delay); jni::Local> getHillshadeAccentColorTransition(jni::JNIEnv&); - jni::Local> createJavaPeer(jni::JNIEnv&); }; // class HillshadeLayer +class HillshadeJavaLayerPeerFactory final : public JavaLayerPeerFactory, public mbgl::style::HillshadeLayerFactory { +public: + ~HillshadeJavaLayerPeerFactory() override; + + // JavaLayerPeerFactory overrides. + jni::Local> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&) final; + jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr) final; + + void registerNative(jni::JNIEnv&) final; + + style::LayerFactory* getLayerFactory() final { return this; } + +}; // class HillshadeJavaLayerPeerFactory + } // namespace android } // namespace mbgl diff --git a/platform/android/src/style/layers/layer.cpp b/platform/android/src/style/layers/layer.cpp index bb543a7639..2f335b6ff3 100644 --- a/platform/android/src/style/layers/layer.cpp +++ b/platform/android/src/style/layers/layer.cpp @@ -37,7 +37,7 @@ namespace android { /** * Invoked when the construction is initiated from the jvm through a subclass */ - Layer::Layer(jni::JNIEnv&, std::unique_ptr coreLayer) + Layer::Layer(std::unique_ptr coreLayer) : ownedLayer(std::move(coreLayer)) , layer(*ownedLayer) { } diff --git a/platform/android/src/style/layers/layer.cpp.ejs b/platform/android/src/style/layers/layer.cpp.ejs index 5fd8537c5a..1489d83a5e 100644 --- a/platform/android/src/style/layers/layer.cpp.ejs +++ b/platform/android/src/style/layers/layer.cpp.ejs @@ -11,6 +11,8 @@ #include "../conversion/property_value.hpp" #include "../conversion/transition_options.hpp" +#include + namespace mbgl { namespace android { @@ -23,13 +25,13 @@ namespace android { * Creates an owning peer object (for layers not attached to the map) from the JVM side */ <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(jni::JNIEnv& env, jni::String& layerId) - : Layer(env, std::make_uniqueLayer>(jni::Make(env, layerId))) { + : Layer(std::make_uniqueLayer>(jni::Make(env, layerId))) { <% } else { -%> /** * Creates an owning peer object (for layers not attached to the map) from the JVM side */ <%- camelize(type) %>Layer::<%- camelize(type) %>Layer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) - : Layer(env, std::make_uniqueLayer>(jni::Make(env, layerId), jni::Make(env, sourceId))) { + : Layer(std::make_uniqueLayer>(jni::Make(env, layerId), jni::Make(env, sourceId))) { <% } -%> } @@ -86,13 +88,29 @@ namespace android { <% } -%> <% } -%> - jni::Local> <%- camelize(type) %>Layer::createJavaPeer(jni::JNIEnv& env) { - static auto& javaClass = jni::Class<<%- camelize(type) %>Layer>::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - return javaClass.New(env, constructor, reinterpret_cast(this)); + // <%- camelize(type) %>JavaLayerPeerFactory + + <%- camelize(type) %>JavaLayerPeerFactory::~<%- camelize(type) %>JavaLayerPeerFactory() = default; + + namespace { + jni::Local> createJavaPeer(jni::JNIEnv& env, Layer* layer) { + static auto& javaClass = jni::Class<<%- camelize(type) %>Layer>::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(layer)); + } + } // namespace + + jni::Local> <%- camelize(type) %>JavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, mbgl::style::Layer& layer) { + assert(layer.baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new <%- camelize(type) %>Layer(map, to<%- camelize(type) %>Layer(layer))); + } + + jni::Local> <%- camelize(type) %>JavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr layer) { + assert(layer->baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new <%- camelize(type) %>Layer(map, std::unique_ptrLayer>(static_castLayer*>(layer.release())))); } - void <%- camelize(type) %>Layer::registerNative(jni::JNIEnv& env) { + void <%- camelize(type) %>JavaLayerPeerFactory::registerNative(jni::JNIEnv& env) { // Lookup the class static auto& javaClass = jni::Class<<%- camelize(type) %>Layer>::Singleton(env); diff --git a/platform/android/src/style/layers/layer.hpp b/platform/android/src/style/layers/layer.hpp index ab3b1d339d..633630b891 100644 --- a/platform/android/src/style/layers/layer.hpp +++ b/platform/android/src/style/layers/layer.hpp @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include "../../gson/json_array.hpp" @@ -11,35 +10,17 @@ namespace mbgl { - namespace android { -class Layer : private mbgl::util::noncopyable { +class Layer { public: static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/Layer"; }; static void registerNative(jni::JNIEnv&); - /* - * Called when a non-owning peer object is created on the c++ side - */ - Layer(mbgl::Map&, mbgl::style::Layer&); - - /* - * Called when a owning peer object is created on the c++ side - */ - Layer(mbgl::Map&, std::unique_ptr); - - /* - * Called when a Java object was created from the jvm side - */ - Layer(jni::JNIEnv&, std::unique_ptr); - virtual ~Layer(); - virtual jni::Local> createJavaPeer(jni::JNIEnv&) = 0; - /** * Set core layer (ie return ownership after remove) */ @@ -82,6 +63,21 @@ public: jni::Local> getVisibility(jni::JNIEnv&); protected: + /* + * Called when a non-owning peer object is created on the c++ side + */ + Layer(mbgl::Map&, mbgl::style::Layer&); + + /* + * Called when a owning peer object is created on the c++ side + */ + Layer(mbgl::Map&, std::unique_ptr); + + /* + * Called when a Java object was created from the jvm side + */ + Layer(std::unique_ptr); + // Release the owned view and return it std::unique_ptr releaseCoreLayer(); @@ -95,5 +91,35 @@ protected: mbgl::Map* map; }; +/** + * @brief A factory class for a layer Java peer objects of a certain type. + */ +class JavaLayerPeerFactory { +public: + virtual ~JavaLayerPeerFactory() = default; + /** + * @brief Create a non-owning peer. + */ + virtual jni::Local> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&) = 0; + + /** + * @brief Create an owning peer. + */ + virtual jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr) = 0; + + /** + * @brief Register peer methods. + */ + virtual void registerNative(jni::JNIEnv&) = 0; + + /** + * @brief Get the corresponding layer factory. + * + * @return style::LayerFactory* must not be \c nullptr. + */ + virtual style::LayerFactory* getLayerFactory() = 0; +}; + + } // namespace android } // namespace mbgl diff --git a/platform/android/src/style/layers/layer.hpp.ejs b/platform/android/src/style/layers/layer.hpp.ejs index 5ceab0dcfa..5791c16501 100644 --- a/platform/android/src/style/layers/layer.hpp.ejs +++ b/platform/android/src/style/layers/layer.hpp.ejs @@ -19,8 +19,6 @@ public: using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/<%- camelize(type) %>Layer"; }; - static void registerNative(jni::JNIEnv&); - <% if (type === 'background') { -%> <%- camelize(type) %>Layer(jni::JNIEnv&, jni::String&); <% } else { -%> @@ -42,9 +40,22 @@ public: jni::Local> get<%- camelize(property.name) %>Transition(jni::JNIEnv&); <% } -%> <% } -%> - jni::Local> createJavaPeer(jni::JNIEnv&); }; // class <%- camelize(type) %>Layer +class <%- camelize(type) %>JavaLayerPeerFactory final : public JavaLayerPeerFactory, public mbgl::style::<%- camelize(type) %>LayerFactory { +public: + ~<%- camelize(type) %>JavaLayerPeerFactory() override; + + // JavaLayerPeerFactory overrides. + jni::Local> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&) final; + jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr) final; + + void registerNative(jni::JNIEnv&) final; + + style::LayerFactory* getLayerFactory() final { return this; } + +}; // class <%- camelize(type) %>JavaLayerPeerFactory + } // namespace android } // namespace mbgl diff --git a/platform/android/src/style/layers/layers.cpp b/platform/android/src/style/layers/layers.cpp index da870aa0e3..30421d31dd 100644 --- a/platform/android/src/style/layers/layers.cpp +++ b/platform/android/src/style/layers/layers.cpp @@ -1,6 +1,7 @@ #include "layers.hpp" #include +#include #include #include #include @@ -12,6 +13,10 @@ #include #include +#include +#include +#include + #include "background_layer.hpp" #include "circle_layer.hpp" #include "custom_layer.hpp" @@ -22,81 +27,88 @@ #include "line_layer.hpp" #include "raster_layer.hpp" #include "symbol_layer.hpp" -#include "unknown_layer.hpp" #include "fill_extrusion_layer.hpp" namespace mbgl { namespace android { -template -inline std::unique_ptr to(std::unique_ptr layer) { - return std::unique_ptr(static_cast(layer.release())); +LayerManagerAndroid::LayerManagerAndroid() { + factories.emplace_back(std::unique_ptr(new FillJavaLayerPeerFactory)); + factories.emplace_back(std::unique_ptr(new LineJavaLayerPeerFactory)); + factories.emplace_back(std::unique_ptr(new CircleJavaLayerPeerFactory)); + factories.emplace_back(std::unique_ptr(new SymbolJavaLayerPeerFactory)); + factories.emplace_back(std::unique_ptr(new RasterJavaLayerPeerFactory)); + factories.emplace_back(std::unique_ptr(new BackgroundJavaLayerPeerFactory)); + factories.emplace_back(std::unique_ptr(new HillshadeJavaLayerPeerFactory)); + factories.emplace_back(std::unique_ptr(new FillExtrusionJavaLayerPeerFactory)); + factories.emplace_back(std::unique_ptr(new HeatmapJavaLayerPeerFactory)); + factories.emplace_back(std::unique_ptr(new CustomJavaLayerPeerFactory)); } -template -inline T& to(style::Layer& layer) { - return static_cast(layer); +LayerManagerAndroid::~LayerManagerAndroid() = default; + +jni::Local> LayerManagerAndroid::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, mbgl::style::Layer& layer) { + if (JavaLayerPeerFactory* factory = getPeerFactory(&layer)) { + return factory->createJavaLayerPeer(env, map, layer); + } + return jni::Local>(); } -template -std::unique_ptr initializeLayerPeer(Map& map, style::LayerType type, T&& layer) { - switch (type) { - case style::LayerType::Fill: - return std::unique_ptr(new FillLayer(map, to(std::forward(layer)))); - case style::LayerType::Line: - return std::unique_ptr(new LineLayer(map, to(std::forward(layer)))); - case style::LayerType::Circle: - return std::unique_ptr(new CircleLayer(map, to(std::forward(layer)))); - case style::LayerType::Symbol: - return std::unique_ptr(new SymbolLayer(map, to(std::forward(layer)))); - case style::LayerType::Raster: - return std::unique_ptr(new RasterLayer(map, to(std::forward(layer)))); - case style::LayerType::Background: - return std::unique_ptr(new BackgroundLayer(map, to(std::forward(layer)))); - case style::LayerType::Hillshade: - return std::unique_ptr(new HillshadeLayer(map, to(std::forward(layer)))); - case style::LayerType::Custom: - return std::unique_ptr(new CustomLayer(map, to(std::forward(layer)))); - case style::LayerType::FillExtrusion: - return std::unique_ptr(new FillExtrusionLayer(map, to(std::forward(layer)))); - case style::LayerType::Heatmap: - return std::unique_ptr(new HeatmapLayer(map, to(std::forward(layer)))); +jni::Local> LayerManagerAndroid::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr layer) { + if (JavaLayerPeerFactory* factory = getPeerFactory(layer.get())) { + return factory->createJavaLayerPeer(env, map, std::move(layer)); } - // Not reachable, but placate GCC. - assert(false); - return std::unique_ptr(new UnknownLayer(map, std::forward(layer))); + return jni::Local>(); } -jni::Local> createJavaLayerPeer(jni::JNIEnv& env, Map& map, style::Layer& coreLayer) { - std::unique_ptr peerLayer = initializeLayerPeer(map, coreLayer.getType(), coreLayer); - jni::Local> result = peerLayer->createJavaPeer(env); - peerLayer.release(); - return result; +void LayerManagerAndroid::registerNative(jni::JNIEnv& env) { + Layer::registerNative(env); + for (const auto& factory: factories) { + factory->registerNative(env); + } } -jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr coreLayer) { - auto type = coreLayer->getType(); - std::unique_ptr peerLayer = initializeLayerPeer(map, type, std::move(coreLayer)); - jni::Local> result = peerLayer->createJavaPeer(env); - peerLayer.release(); - return result; +JavaLayerPeerFactory* LayerManagerAndroid::getPeerFactory(mbgl::style::Layer* layer) { + auto* layerFactory = layer->baseImpl->getLayerFactory(); + assert(layerFactory); + for (const auto& factory: factories) { + if (factory->getLayerFactory() == layerFactory) { + return factory.get(); + } + } + assert(false); + return nullptr; } -void registerNativeLayers(jni::JNIEnv& env) { - Layer::registerNative(env); - BackgroundLayer::registerNative(env); - CircleLayer::registerNative(env); - CustomLayer::registerNative(env); - FillExtrusionLayer::registerNative(env); - FillLayer::registerNative(env); - HeatmapLayer::registerNative(env); - HillshadeLayer::registerNative(env); - LineLayer::registerNative(env); - RasterLayer::registerNative(env); - SymbolLayer::registerNative(env); - UnknownLayer::registerNative(env); +std::unique_ptr LayerManagerAndroid::createLayer(const std::string& type, const std::string& id, const style::conversion::Convertible& value, style::conversion::Error& error) { + for (const auto& factory: factories) { + auto* layerFactory = factory->getLayerFactory(); + if (layerFactory->supportsType(type)) { + if (auto layer = layerFactory->createLayer(id, value)) { + return layer; + } + error.message = "Error parsing a layer of type: " + type; + return nullptr; + } + } + error.message = "Unsupported layer type: " + type; + return nullptr; +} + +// static +LayerManagerAndroid* LayerManagerAndroid::get() { + static LayerManagerAndroid impl; + return &impl; } } // namespace android + +namespace style { +// static +LayerManager* LayerManager::get() { + return android::LayerManagerAndroid::get(); +} + +} // style } // namespace mbgl diff --git a/platform/android/src/style/layers/layers.hpp b/platform/android/src/style/layers/layers.hpp index c9a6ba2e66..7684108555 100644 --- a/platform/android/src/style/layers/layers.hpp +++ b/platform/android/src/style/layers/layers.hpp @@ -7,20 +7,33 @@ #include +#include +#include + namespace mbgl { namespace android { /** - * Create a non-owning peer + * @brief A singleton class forwarding calls to the corresponding \c JavaLayerPeerFactory instance. */ -jni::Local> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&); - -/** - * Create an owning peer - */ -jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr); - -void registerNativeLayers(jni::JNIEnv&); +class LayerManagerAndroid : public mbgl::style::LayerManager { +public: + ~LayerManagerAndroid() override; + static LayerManagerAndroid* get(); + + jni::Local> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&); + jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr); + + void registerNative(jni::JNIEnv&); + +private: + LayerManagerAndroid(); + JavaLayerPeerFactory* getPeerFactory(mbgl::style::Layer*); + // mbgl:style::LayerManager overrides. + std::unique_ptr createLayer(const std::string& type, const std::string& id, const style::conversion::Convertible& value, style::conversion::Error& error) final; + + std::vector> factories; +}; } } diff --git a/platform/android/src/style/layers/line_layer.cpp b/platform/android/src/style/layers/line_layer.cpp index 28a6c54749..69b745b89c 100644 --- a/platform/android/src/style/layers/line_layer.cpp +++ b/platform/android/src/style/layers/line_layer.cpp @@ -7,6 +7,8 @@ #include "../conversion/property_value.hpp" #include "../conversion/transition_options.hpp" +#include + namespace mbgl { namespace android { @@ -18,7 +20,7 @@ namespace android { * Creates an owning peer object (for layers not attached to the map) from the JVM side */ LineLayer::LineLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) - : Layer(env, std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { + : Layer(std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { } /** @@ -232,13 +234,29 @@ namespace android { } - jni::Local> LineLayer::createJavaPeer(jni::JNIEnv& env) { - static auto& javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - return javaClass.New(env, constructor, reinterpret_cast(this)); + // LineJavaLayerPeerFactory + + LineJavaLayerPeerFactory::~LineJavaLayerPeerFactory() = default; + + namespace { + jni::Local> createJavaPeer(jni::JNIEnv& env, Layer* layer) { + static auto& javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(layer)); + } + } // namespace + + jni::Local> LineJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, mbgl::style::Layer& layer) { + assert(layer.baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new LineLayer(map, toLineLayer(layer))); + } + + jni::Local> LineJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr layer) { + assert(layer->baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new LineLayer(map, std::unique_ptr(static_cast(layer.release())))); } - void LineLayer::registerNative(jni::JNIEnv& env) { + void LineJavaLayerPeerFactory::registerNative(jni::JNIEnv& env) { // Lookup the class static auto& javaClass = jni::Class::Singleton(env); diff --git a/platform/android/src/style/layers/line_layer.hpp b/platform/android/src/style/layers/line_layer.hpp index 01be481958..4dbc855ca9 100644 --- a/platform/android/src/style/layers/line_layer.hpp +++ b/platform/android/src/style/layers/line_layer.hpp @@ -15,8 +15,6 @@ public: using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/LineLayer"; }; - static void registerNative(jni::JNIEnv&); - LineLayer(jni::JNIEnv&, jni::String&, jni::String&); LineLayer(mbgl::Map&, mbgl::style::LineLayer&); @@ -74,9 +72,22 @@ public: jni::Local> getLinePatternTransition(jni::JNIEnv&); jni::Local> getLineGradient(jni::JNIEnv&); - jni::Local> createJavaPeer(jni::JNIEnv&); }; // class LineLayer +class LineJavaLayerPeerFactory final : public JavaLayerPeerFactory, public mbgl::style::LineLayerFactory { +public: + ~LineJavaLayerPeerFactory() override; + + // JavaLayerPeerFactory overrides. + jni::Local> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&) final; + jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr) final; + + void registerNative(jni::JNIEnv&) final; + + style::LayerFactory* getLayerFactory() final { return this; } + +}; // class LineJavaLayerPeerFactory + } // namespace android } // namespace mbgl diff --git a/platform/android/src/style/layers/raster_layer.cpp b/platform/android/src/style/layers/raster_layer.cpp index 5acbb8fe89..00286c0f16 100644 --- a/platform/android/src/style/layers/raster_layer.cpp +++ b/platform/android/src/style/layers/raster_layer.cpp @@ -7,6 +7,8 @@ #include "../conversion/property_value.hpp" #include "../conversion/transition_options.hpp" +#include + namespace mbgl { namespace android { @@ -18,7 +20,7 @@ namespace android { * Creates an owning peer object (for layers not attached to the map) from the JVM side */ RasterLayer::RasterLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) - : Layer(env, std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { + : Layer(std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { } /** @@ -158,13 +160,29 @@ namespace android { } - jni::Local> RasterLayer::createJavaPeer(jni::JNIEnv& env) { - static auto& javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - return javaClass.New(env, constructor, reinterpret_cast(this)); + // RasterJavaLayerPeerFactory + + RasterJavaLayerPeerFactory::~RasterJavaLayerPeerFactory() = default; + + namespace { + jni::Local> createJavaPeer(jni::JNIEnv& env, Layer* layer) { + static auto& javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(layer)); + } + } // namespace + + jni::Local> RasterJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, mbgl::style::Layer& layer) { + assert(layer.baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new RasterLayer(map, toRasterLayer(layer))); + } + + jni::Local> RasterJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr layer) { + assert(layer->baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new RasterLayer(map, std::unique_ptr(static_cast(layer.release())))); } - void RasterLayer::registerNative(jni::JNIEnv& env) { + void RasterJavaLayerPeerFactory::registerNative(jni::JNIEnv& env) { // Lookup the class static auto& javaClass = jni::Class::Singleton(env); diff --git a/platform/android/src/style/layers/raster_layer.hpp b/platform/android/src/style/layers/raster_layer.hpp index 40cc47634e..492b3562fc 100644 --- a/platform/android/src/style/layers/raster_layer.hpp +++ b/platform/android/src/style/layers/raster_layer.hpp @@ -15,8 +15,6 @@ public: using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/RasterLayer"; }; - static void registerNative(jni::JNIEnv&); - RasterLayer(jni::JNIEnv&, jni::String&, jni::String&); RasterLayer(mbgl::Map&, mbgl::style::RasterLayer&); @@ -54,9 +52,22 @@ public: jni::Local> getRasterResampling(jni::JNIEnv&); jni::Local> getRasterFadeDuration(jni::JNIEnv&); - jni::Local> createJavaPeer(jni::JNIEnv&); }; // class RasterLayer +class RasterJavaLayerPeerFactory final : public JavaLayerPeerFactory, public mbgl::style::RasterLayerFactory { +public: + ~RasterJavaLayerPeerFactory() override; + + // JavaLayerPeerFactory overrides. + jni::Local> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&) final; + jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr) final; + + void registerNative(jni::JNIEnv&) final; + + style::LayerFactory* getLayerFactory() final { return this; } + +}; // class RasterJavaLayerPeerFactory + } // namespace android } // namespace mbgl diff --git a/platform/android/src/style/layers/symbol_layer.cpp b/platform/android/src/style/layers/symbol_layer.cpp index 27896208a7..646e02ce32 100644 --- a/platform/android/src/style/layers/symbol_layer.cpp +++ b/platform/android/src/style/layers/symbol_layer.cpp @@ -7,6 +7,8 @@ #include "../conversion/property_value.hpp" #include "../conversion/transition_options.hpp" +#include + namespace mbgl { namespace android { @@ -18,7 +20,7 @@ namespace android { * Creates an owning peer object (for layers not attached to the map) from the JVM side */ SymbolLayer::SymbolLayer(jni::JNIEnv& env, jni::String& layerId, jni::String& sourceId) - : Layer(env, std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { + : Layer(std::make_unique(jni::Make(env, layerId), jni::Make(env, sourceId))) { } /** @@ -451,13 +453,29 @@ namespace android { } - jni::Local> SymbolLayer::createJavaPeer(jni::JNIEnv& env) { - static auto& javaClass = jni::Class::Singleton(env); - static auto constructor = javaClass.GetConstructor(env); - return javaClass.New(env, constructor, reinterpret_cast(this)); + // SymbolJavaLayerPeerFactory + + SymbolJavaLayerPeerFactory::~SymbolJavaLayerPeerFactory() = default; + + namespace { + jni::Local> createJavaPeer(jni::JNIEnv& env, Layer* layer) { + static auto& javaClass = jni::Class::Singleton(env); + static auto constructor = javaClass.GetConstructor(env); + return javaClass.New(env, constructor, reinterpret_cast(layer)); + } + } // namespace + + jni::Local> SymbolJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, mbgl::style::Layer& layer) { + assert(layer.baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new SymbolLayer(map, toSymbolLayer(layer))); + } + + jni::Local> SymbolJavaLayerPeerFactory::createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr layer) { + assert(layer->baseImpl->getLayerFactory() == this); + return createJavaPeer(env, new SymbolLayer(map, std::unique_ptr(static_cast(layer.release())))); } - void SymbolLayer::registerNative(jni::JNIEnv& env) { + void SymbolJavaLayerPeerFactory::registerNative(jni::JNIEnv& env) { // Lookup the class static auto& javaClass = jni::Class::Singleton(env); diff --git a/platform/android/src/style/layers/symbol_layer.hpp b/platform/android/src/style/layers/symbol_layer.hpp index 9887fd8fb7..5df7ac3687 100644 --- a/platform/android/src/style/layers/symbol_layer.hpp +++ b/platform/android/src/style/layers/symbol_layer.hpp @@ -15,8 +15,6 @@ public: using SuperTag = Layer; static constexpr auto Name() { return "com/mapbox/mapboxsdk/style/layers/SymbolLayer"; }; - static void registerNative(jni::JNIEnv&); - SymbolLayer(jni::JNIEnv&, jni::String&, jni::String&); SymbolLayer(mbgl::Map&, mbgl::style::SymbolLayer&); @@ -152,9 +150,22 @@ public: jni::Local> getTextTranslateTransition(jni::JNIEnv&); jni::Local> getTextTranslateAnchor(jni::JNIEnv&); - jni::Local> createJavaPeer(jni::JNIEnv&); }; // class SymbolLayer +class SymbolJavaLayerPeerFactory final : public JavaLayerPeerFactory, public mbgl::style::SymbolLayerFactory { +public: + ~SymbolJavaLayerPeerFactory() override; + + // JavaLayerPeerFactory overrides. + jni::Local> createJavaLayerPeer(jni::JNIEnv&, mbgl::Map&, mbgl::style::Layer&) final; + jni::Local> createJavaLayerPeer(jni::JNIEnv& env, mbgl::Map& map, std::unique_ptr) final; + + void registerNative(jni::JNIEnv&) final; + + style::LayerFactory* getLayerFactory() final { return this; } + +}; // class SymbolJavaLayerPeerFactory + } // namespace android } // namespace mbgl diff --git a/platform/android/src/style/layers/unknown_layer.cpp b/platform/android/src/style/layers/unknown_layer.cpp index 5c770012bd..bf311aff37 100644 --- a/platform/android/src/style/layers/unknown_layer.cpp +++ b/platform/android/src/style/layers/unknown_layer.cpp @@ -22,10 +22,10 @@ namespace android { : Layer(map, std::move(coreLayer)) { } - jni::Local> UnknownLayer::createJavaPeer(jni::JNIEnv& env) { + jni::Local> UnknownLayer::createJavaPeer(jni::JNIEnv& env, Layer* layer) { static auto& javaClass = jni::Class::Singleton(env); static auto constructor = javaClass.GetConstructor(env); - return javaClass.New(env, constructor, reinterpret_cast(this)); + return javaClass.New(env, constructor, reinterpret_cast(layer)); } void UnknownLayer::registerNative(jni::JNIEnv& env) { diff --git a/platform/android/src/style/layers/unknown_layer.hpp b/platform/android/src/style/layers/unknown_layer.hpp index 692e2f5db4..1b64ba1b3d 100644 --- a/platform/android/src/style/layers/unknown_layer.hpp +++ b/platform/android/src/style/layers/unknown_layer.hpp @@ -20,7 +20,7 @@ public: ~UnknownLayer() = default; - jni::Local> createJavaPeer(jni::JNIEnv&); + static jni::Local> createJavaPeer(jni::JNIEnv&, Layer*); }; // class UnknownLayer -- cgit v1.2.1