[node] Add support for feature state APIs

This commit is contained in:
Juha Alanen
2019-08-28 13:34:11 +03:00
committed by Juha Alanen
parent fd179de6fb
commit a186e6a27d
3 changed files with 231 additions and 0 deletions

View File

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