#include "layer.hpp" #include "../android_conversion.hpp" #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Java -> C++ conversion #include #include #include #include // C++ -> Java conversion #include "../conversion/property_value.hpp" #include #include namespace mbgl { namespace android { /** * Invoked when the construction is initiated from the jvm through a subclass */ Layer::Layer(jni::JNIEnv&, std::unique_ptr coreLayer) : ownedLayer(std::move(coreLayer)) , layer(*ownedLayer) { } /** * Takes a non-owning reference. For lookup methods */ Layer::Layer(mbgl::Map& coreMap, mbgl::style::Layer& coreLayer) : layer(coreLayer) , map(&coreMap) { } /** * Takes a owning reference. Ownership is transfered to this peer, eg after removing * from the map */ Layer::Layer(mbgl::Map& coreMap, std::unique_ptr coreLayer) : ownedLayer(std::move(coreLayer)) , layer(*ownedLayer) , map(&coreMap) { } Layer::~Layer() { } void Layer::addToMap(mbgl::Map& _map, mbgl::optional before) { // Check to see if we own the layer first if (!ownedLayer) { throw std::runtime_error("Cannot add layer twice"); } // Add layer to map _map.getStyle().addLayer(releaseCoreLayer(), before); // Save pointer to the map this->map = &_map; } void Layer::setLayer(std::unique_ptr sourceLayer) { this->ownedLayer = std::move(sourceLayer); } std::unique_ptr Layer::releaseCoreLayer() { assert(ownedLayer != nullptr); return std::move(ownedLayer); } jni::String Layer::getId(jni::JNIEnv& env) { return jni::Make(env, layer.getID()); } style::Layer& Layer::get() { return layer; } void Layer::setLayoutProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) { // Convert and set property optional error = mbgl::style::conversion::setLayoutProperty(layer, jni::Make(env, jname), Value(env, jvalue)); if (error) { mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make(env, jname) + " " + error->message); return; } } void Layer::setPaintProperty(jni::JNIEnv& env, jni::String jname, jni::Object<> jvalue) { // Convert and set property optional error = mbgl::style::conversion::setPaintProperty(layer, jni::Make(env, jname), Value(env, jvalue)); if (error) { mbgl::Log::Error(mbgl::Event::JNI, "Error setting property: " + jni::Make(env, jname) + " " + error->message); return; } } struct SetFilterEvaluator { style::Filter filter; void operator()(style::BackgroundLayer&) { Log::Warning(mbgl::Event::JNI, "BackgroundLayer doesn't support filters"); } void operator()(style::CustomLayer&) { Log::Warning(mbgl::Event::JNI, "CustomLayer doesn't support filters"); } void operator()(style::RasterLayer&) { Log::Warning(mbgl::Event::JNI, "RasterLayer doesn't support filters"); } void operator()(style::HillshadeLayer&) { Log::Warning(mbgl::Event::JNI, "HillshadeLayer doesn't support filters"); } template void operator()(LayerType& layer) { layer.setFilter(filter); } }; void Layer::setFilter(jni::JNIEnv& env, jni::Array> jfilter) { using namespace mbgl::style; using namespace mbgl::style::conversion; Error error; optional converted = convert(Value(env, jfilter), error); if (!converted) { mbgl::Log::Error(mbgl::Event::JNI, "Error setting filter: " + error.message); return; } layer.accept(SetFilterEvaluator {std::move(*converted)}); } struct GetFilterEvaluator { mbgl::style::Filter noop(std::string layerType) { Log::Warning(mbgl::Event::JNI, "%s doesn't support filter", layerType.c_str()); return {}; } mbgl::style::Filter operator()(style::BackgroundLayer&) { return noop("BackgroundLayer"); } mbgl::style::Filter operator()(style::CustomLayer&) { return noop("CustomLayer"); } mbgl::style::Filter operator()(style::RasterLayer&) { return noop("RasterLayer"); } mbgl::style::Filter operator()(style::HillshadeLayer&) { return noop("HillshadeLayer"); } template mbgl::style::Filter operator()(LayerType& layer) { return layer.getFilter(); } }; jni::Object Layer::getFilter(jni::JNIEnv& env) { using namespace mbgl::style; using namespace mbgl::style::conversion; Filter filter = layer.accept(GetFilterEvaluator()); jni::Object converted; if (filter.is()) { ExpressionFilter filterExpression = filter.get(); mbgl::Value expressionValue = filterExpression.expression.get()->serialize(); converted = gson::JsonElement::New(env, expressionValue); } return converted; } struct SetSourceLayerEvaluator { std::string sourceLayer; void operator()(style::BackgroundLayer&) { Log::Warning(mbgl::Event::JNI, "BackgroundLayer doesn't support source layer"); } void operator()(style::CustomLayer&) { Log::Warning(mbgl::Event::JNI, "CustomLayer doesn't support source layer"); } void operator()(style::RasterLayer&) { Log::Warning(mbgl::Event::JNI, "RasterLayer doesn't support source layer"); } void operator()(style::HillshadeLayer&) { Log::Warning(mbgl::Event::JNI, "HillshadeLayer doesn't support source layer"); } template void operator()(LayerType& layer) { layer.setSourceLayer(sourceLayer); } }; void Layer::setSourceLayer(jni::JNIEnv& env, jni::String sourceLayer) { layer.accept(SetSourceLayerEvaluator {jni::Make(env, sourceLayer)}); } struct GetSourceLayerEvaluator { std::string noop(std::string layerType) { Log::Warning(mbgl::Event::JNI, "%s doesn't support source layer", layerType.c_str()); return {}; } std::string operator()(style::BackgroundLayer&) { return noop("BackgroundLayer"); } std::string operator()(style::CustomLayer&) { return noop("CustomLayer"); } std::string operator()(style::RasterLayer&) { return noop("RasterLayer"); } std::string operator()(style::HillshadeLayer&) { return noop("HillshadeLayer"); } template std::string operator()(LayerType& layer) { return layer.getSourceLayer(); } }; jni::String Layer::getSourceLayer(jni::JNIEnv& env) { return jni::Make(env, layer.accept(GetSourceLayerEvaluator())); } jni::jfloat Layer::getMinZoom(jni::JNIEnv&){ return layer.getMinZoom(); } jni::jfloat Layer::getMaxZoom(jni::JNIEnv&) { return layer.getMaxZoom(); } void Layer::setMinZoom(jni::JNIEnv&, jni::jfloat zoom) { layer.setMinZoom(zoom); } void Layer::setMaxZoom(jni::JNIEnv&, jni::jfloat zoom) { layer.setMaxZoom(zoom); } jni::Object Layer::getVisibility(jni::JNIEnv& env) { using namespace mbgl::android::conversion; return jni::Object(*convert(env, layer.getVisibility())); } jni::Class Layer::javaClass; void Layer::registerNative(jni::JNIEnv& env) { // Lookup the class Layer::javaClass = *jni::Class::Find(env).NewGlobalRef(env).release(); #define METHOD(MethodPtr, name) jni::MakeNativePeerMethod(name) // Register the peer jni::RegisterNativePeer(env, Layer::javaClass, "nativePtr", METHOD(&Layer::getId, "nativeGetId"), METHOD(&Layer::setLayoutProperty, "nativeSetLayoutProperty"), METHOD(&Layer::setPaintProperty, "nativeSetPaintProperty"), METHOD(&Layer::setFilter, "nativeSetFilter"), METHOD(&Layer::getFilter, "nativeGetFilter"), METHOD(&Layer::setSourceLayer, "nativeSetSourceLayer"), METHOD(&Layer::getSourceLayer, "nativeGetSourceLayer"), METHOD(&Layer::getMinZoom, "nativeGetMinZoom"), METHOD(&Layer::getMaxZoom, "nativeGetMaxZoom"), METHOD(&Layer::setMinZoom, "nativeSetMinZoom"), METHOD(&Layer::setMaxZoom, "nativeSetMaxZoom"), METHOD(&Layer::getVisibility, "nativeGetVisibility") ); } } // namespace android } // namespace mbgl