summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJuha Alanen <juha.alanen@mapbox.com>2019-08-28 13:34:11 +0300
committerJuha Alanen <19551460+jmalanen@users.noreply.github.com>2019-09-18 14:29:15 +0300
commita186e6a27d79ca3ed1eb6fadce656df5e0e2b89f (patch)
treef80803d4318b1fefbb031b695b6b60ce5e52557e
parentfd179de6fb8ddc170db66d028ac7fe871b84394a (diff)
downloadqtlocation-mapboxgl-a186e6a27d79ca3ed1eb6fadce656df5e0e2b89f.tar.gz
[node] Add support for feature state APIs
-rw-r--r--platform/node/src/node_feature.cpp6
-rw-r--r--platform/node/src/node_map.cpp221
-rw-r--r--platform/node/src/node_map.hpp4
3 files changed, 231 insertions, 0 deletions
diff --git a/platform/node/src/node_feature.cpp b/platform/node/src/node_feature.cpp
index 2dfab686a7..646cc23338 100644
--- a/platform/node/src/node_feature.cpp
+++ b/platform/node/src/node_feature.cpp
@@ -167,6 +167,12 @@ v8::Local<v8::Object> toJS(const Feature& feature) {
Nan::Set(result, Nan::New("id").ToLocalChecked(), FeatureIdentifier::visit(feature.id, ToValue()));
}
+ Nan::Set(result, Nan::New("source").ToLocalChecked(), toJS(feature.source));
+ if (!feature.sourceLayer.empty()) {
+ Nan::Set(result, Nan::New("sourceLayer").ToLocalChecked(), toJS(feature.sourceLayer));
+ }
+ Nan::Set(result, Nan::New("state").ToLocalChecked(), toJS(feature.state));
+
return scope.Escape(result);
}
diff --git a/platform/node/src/node_map.cpp b/platform/node/src/node_map.cpp
index 641816dc00..d9bee1c840 100644
--- a/platform/node/src/node_map.cpp
+++ b/platform/node/src/node_map.cpp
@@ -117,6 +117,9 @@ ParseError)JS").ToLocalChecked()).ToLocalChecked();
Nan::SetPrototypeMethod(tpl, "setAxonometric", SetAxonometric);
Nan::SetPrototypeMethod(tpl, "setXSkew", SetXSkew);
Nan::SetPrototypeMethod(tpl, "setYSkew", SetYSkew);
+ Nan::SetPrototypeMethod(tpl, "setFeatureState", SetFeatureState);
+ Nan::SetPrototypeMethod(tpl, "getFeatureState", GetFeatureState);
+ Nan::SetPrototypeMethod(tpl, "removeFeatureState", RemoveFeatureState);
Nan::SetPrototypeMethod(tpl, "dumpDebugLogs", DumpDebugLogs);
Nan::SetPrototypeMethod(tpl, "queryRenderedFeatures", QueryRenderedFeatures);
@@ -1099,6 +1102,224 @@ void NodeMap::SetYSkew(const Nan::FunctionCallbackInfo<v8::Value>& info) {
info.GetReturnValue().SetUndefined();
}
+void NodeMap::SetFeatureState(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ using namespace mbgl;
+ using namespace mbgl::style::conversion;
+
+ auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
+ if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
+
+ if (info.Length() < 2) {
+ return Nan::ThrowTypeError("Two arguments required");
+ }
+
+ if (!info[0]->IsObject() || !info[1]->IsObject()) {
+ return Nan::ThrowTypeError("Both arguments must be objects");
+ }
+
+ std::string sourceID, featureID;
+ mbgl::optional<std::string> sourceLayerID;
+ auto feature = Nan::To<v8::Object>(info[0]).ToLocalChecked();
+ if (Nan::Has(feature, Nan::New("source").ToLocalChecked()).FromJust()) {
+ auto sourceOption = Nan::Get(feature, Nan::New("source").ToLocalChecked()).ToLocalChecked();
+ if (!sourceOption->IsString()) {
+ return Nan::ThrowTypeError("Requires feature.source property to be a string");
+ }
+ sourceID = *Nan::Utf8String(sourceOption);
+ } else {
+ return Nan::ThrowTypeError("SetFeatureState: Requires feature.source property");
+ }
+
+ if (Nan::Has(feature, Nan::New("sourceLayer").ToLocalChecked()).FromJust()) {
+ auto sourceLayerOption = Nan::Get(feature, Nan::New("sourceLayer").ToLocalChecked()).ToLocalChecked();
+ if (!sourceLayerOption->IsString()) {
+ return Nan::ThrowTypeError("SetFeatureState: Requires feature.sourceLayer property to be a string");
+ }
+ sourceLayerID = { *Nan::Utf8String(sourceLayerOption) };
+ }
+
+ if (Nan::Has(feature, Nan::New("id").ToLocalChecked()).FromJust()) {
+ auto idOption = Nan::Get(feature, Nan::New("id").ToLocalChecked()).ToLocalChecked();
+ if (!idOption->IsString() && !(idOption->IsNumber() || idOption->IsString())) {
+ return Nan::ThrowTypeError("Requires feature.id property to be a string or a number");
+ }
+ featureID = *Nan::Utf8String(idOption);
+ } else {
+ return Nan::ThrowTypeError("SetFeatureState: Requires feature.id property");
+ }
+
+ Convertible state(info[1]);
+
+ if (!isObject(state)) {
+ return Nan::ThrowTypeError("Feature state must be an object");
+ }
+
+ std::string sourceLayer = sourceLayerID.value_or(std::string());
+ std::string stateKey;
+ Value stateValue;
+ bool valueParsed = false;
+ FeatureState newState;
+
+ const std::function<optional<Error> (const std::string&, const Convertible&)> convertFn = [&] (const std::string& k, const Convertible& v) -> optional<Error> {
+ optional<Value> value = toValue(v);
+ if (value) {
+ stateValue = std::move(*value);
+ valueParsed = true;
+ } else if (isArray(v)) {
+ std::vector<Value> array;
+ std::size_t length = arrayLength(v);
+ array.reserve(length);
+ for (size_t i = 0; i < length; ++i) {
+ optional<Value> arrayVal = toValue(arrayMember(v, i));
+ if (arrayVal) {
+ array.emplace_back(*arrayVal);
+ }
+ }
+ std::unordered_map<std::string, Value> result;
+ result[k]= std::move(array);
+ stateValue = std::move(result);
+ valueParsed = true;
+ return {};
+
+ } else if (isObject(v)) {
+ eachMember(v, convertFn);
+
+ }
+ if (!valueParsed) {
+ Nan::ThrowTypeError("Could not get feature state value");
+ return nullopt;
+ }
+ stateKey = k;
+ newState[stateKey] = stateValue;
+ return nullopt;
+ };
+
+ eachMember(state, convertFn);
+
+ try {
+ nodeMap->frontend->getRenderer()->setFeatureState(sourceID, sourceLayerID, featureID, newState);
+ } catch (const std::exception &ex) {
+ return Nan::ThrowError(ex.what());
+ }
+
+ info.GetReturnValue().SetUndefined();
+}
+
+void NodeMap::GetFeatureState(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
+ if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
+
+ if (info.Length() < 1) {
+ return Nan::ThrowTypeError("One argument required");
+ }
+
+ if (!info[0]->IsObject() || !info[1]->IsObject()) {
+ return Nan::ThrowTypeError("Argument must be object");
+ }
+
+ std::string sourceID, featureID;
+ mbgl::optional<std::string> sourceLayerID;
+ auto feature = Nan::To<v8::Object>(info[0]).ToLocalChecked();
+ if (Nan::Has(feature, Nan::New("source").ToLocalChecked()).FromJust()) {
+ auto sourceOption = Nan::Get(feature, Nan::New("source").ToLocalChecked()).ToLocalChecked();
+ if (!sourceOption->IsString()) {
+ return Nan::ThrowTypeError("Requires feature.source property to be a string");
+ }
+ sourceID = *Nan::Utf8String(sourceOption);
+ } else {
+ return Nan::ThrowTypeError("GetFeatureState: Requires feature.source property");
+ }
+
+ if (Nan::Has(feature, Nan::New("sourceLayer").ToLocalChecked()).FromJust()) {
+ auto sourceLayerOption = Nan::Get(feature, Nan::New("sourceLayer").ToLocalChecked()).ToLocalChecked();
+ if (!sourceLayerOption->IsString()) {
+ return Nan::ThrowTypeError("GetFeatureState: Requires feature.sourceLayer property to be a string");
+ }
+ sourceLayerID = { *Nan::Utf8String(sourceLayerOption) };
+ }
+
+ if (Nan::Has(feature, Nan::New("id").ToLocalChecked()).FromJust()) {
+ auto idOption = Nan::Get(feature, Nan::New("id").ToLocalChecked()).ToLocalChecked();
+ if (!idOption->IsString() && !(idOption->IsNumber() || idOption->IsString())) {
+ return Nan::ThrowTypeError("Requires feature.id property to be a string or a number");
+ }
+ featureID = *Nan::Utf8String(idOption);
+ } else {
+ return Nan::ThrowTypeError("GetFeatureState: Requires feature.id property");
+ }
+
+ mbgl::FeatureState state;
+ try {
+ nodeMap->frontend->getRenderer()->getFeatureState(state, sourceID, sourceLayerID, featureID);
+ } catch (const std::exception &ex) {
+ return Nan::ThrowError(ex.what());
+ }
+
+ info.GetReturnValue().SetUndefined();
+}
+
+void NodeMap::RemoveFeatureState(const Nan::FunctionCallbackInfo<v8::Value>& info) {
+ auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
+ if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
+
+ if (info.Length() < 1) {
+ return Nan::ThrowTypeError("At least one argument required");
+ }
+
+ if (!info[0]->IsObject()) {
+ return Nan::ThrowTypeError("Argument 1 must be object");
+ }
+
+ if (info.Length() == 2 && !info[1]->IsString()) {
+ return Nan::ThrowTypeError("argument 2 must be string");
+ }
+
+ std::string sourceID;
+ mbgl::optional<std::string> sourceLayerID, featureID, stateKey;
+ auto feature = Nan::To<v8::Object>(info[0]).ToLocalChecked();
+ if (Nan::Has(feature, Nan::New("source").ToLocalChecked()).FromJust()) {
+ auto sourceOption = Nan::Get(feature, Nan::New("source").ToLocalChecked()).ToLocalChecked();
+ if (!sourceOption->IsString()) {
+ return Nan::ThrowTypeError("Requires feature.source property to be a string");
+ }
+ sourceID = *Nan::Utf8String(sourceOption);
+ } else {
+ return Nan::ThrowTypeError("RemoveFeatureState: Requires feature.source property");
+ }
+
+ if (Nan::Has(feature, Nan::New("sourceLayer").ToLocalChecked()).FromJust()) {
+ auto sourceLayerOption = Nan::Get(feature, Nan::New("sourceLayer").ToLocalChecked()).ToLocalChecked();
+ if (!sourceLayerOption->IsString()) {
+ return Nan::ThrowTypeError("RemoveFeatureState: Requires feature.sourceLayer property to be a string");
+ }
+ sourceLayerID = { *Nan::Utf8String(sourceLayerOption) };
+ }
+
+ if (Nan::Has(feature, Nan::New("id").ToLocalChecked()).FromJust()) {
+ auto idOption = Nan::Get(feature, Nan::New("id").ToLocalChecked()).ToLocalChecked();
+ if (!idOption->IsString() && !(idOption->IsNumber() || idOption->IsString())) {
+ return Nan::ThrowTypeError("Requires feature.id property to be a string or a number");
+ }
+ featureID = { *Nan::Utf8String(idOption) };
+ }
+
+ if (info.Length() == 2) {
+ auto keyParam = Nan::To<v8::String>(info[1]).ToLocalChecked();
+ if (!keyParam->IsString()) {
+ return Nan::ThrowTypeError("RemoveFeatureState: Requires feature key property to be a string");
+ }
+ stateKey = { *Nan::Utf8String(keyParam) };
+ }
+
+ try {
+ nodeMap->frontend->getRenderer()->removeFeatureState(sourceID, sourceLayerID, featureID, stateKey);
+ } catch (const std::exception &ex) {
+ return Nan::ThrowError(ex.what());
+ }
+
+ info.GetReturnValue().SetUndefined();
+}
+
void NodeMap::DumpDebugLogs(const Nan::FunctionCallbackInfo<v8::Value>& info) {
auto nodeMap = Nan::ObjectWrap::Unwrap<NodeMap>(info.Holder());
if (!nodeMap->map) return Nan::ThrowError(releasedMessage());
diff --git a/platform/node/src/node_map.hpp b/platform/node/src/node_map.hpp
index 486754c1c3..381e10381b 100644
--- a/platform/node/src/node_map.hpp
+++ b/platform/node/src/node_map.hpp
@@ -64,6 +64,10 @@ public:
static void DumpDebugLogs(const Nan::FunctionCallbackInfo<v8::Value>&);
static void QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void SetFeatureState(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void GetFeatureState(const Nan::FunctionCallbackInfo<v8::Value>&);
+ static void RemoveFeatureState(const Nan::FunctionCallbackInfo<v8::Value>&);
+
static v8::Local<v8::Value> ParseError(const char* msg);
void startRender(RenderOptions options);