OpenRoadCode
Public API reference for OpenRoadCode
Loading...
Searching...
No Matches
map_feature_hover.hpp
1// SPDX-FileCopyrightText: 2026 Mark G. Russell
2// SPDX-License-Identifier: MIT
3#pragma once
4
5#include <rapidjson/document.h>
6#include <rapidjson/stringbuffer.h>
7#include <rapidjson/writer.h>
8#include <string>
9#include <utility>
10
11// Keep hover local to the renderer, using identities from the existing click contracts.
12class MapFeatureHover {
13public:
14 explicit MapFeatureHover(std::string property = "weather_city_id",
15 std::string prefix = "weather-city:",
16 std::string flag = "weather_city_hover")
17 : identityProperty(std::move(property)), identityPrefix(std::move(prefix)), hoverFlag(std::move(flag)) {}
18
19 bool setData(const std::string& data) {
20 featuresData = data;
21 return select(identity);
22 }
23
24 bool select(const std::string& candidate) {
25 rapidjson::Document input;
26 input.Parse(featuresData.c_str());
27 rapidjson::Document output;
28 output.SetObject();
29 auto& allocator = output.GetAllocator();
30 output.AddMember("type", "FeatureCollection", allocator);
31 rapidjson::Value features(rapidjson::kArrayType);
32 std::string matched;
33 if (!candidate.empty() && !input.HasParseError() && input.IsObject() &&
34 input.HasMember("features") && input["features"].IsArray()) {
35 for (const auto& feature : input["features"].GetArray()) {
36 if (!feature.IsObject() || !feature.HasMember("properties") || !feature["properties"].IsObject())
37 continue;
38 const auto& properties = feature["properties"];
39 if (!properties.HasMember(identityProperty.c_str()) || !properties[identityProperty.c_str()].IsString() ||
40 candidate != properties[identityProperty.c_str()].GetString() || candidate.rfind(identityPrefix, 0) != 0)
41 continue;
42 rapidjson::Value copy;
43 copy.CopyFrom(feature, allocator);
44 copy["properties"].RemoveMember(hoverFlag.c_str());
45 copy["properties"].AddMember(rapidjson::Value(hoverFlag.c_str(), allocator), rapidjson::Value(true), allocator);
46 features.PushBack(copy, allocator);
47 matched = candidate;
48 break;
49 }
50 }
51 output.AddMember("features", features, allocator);
52 rapidjson::StringBuffer buffer;
53 rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
54 output.Accept(writer);
55 const std::string next = buffer.GetString();
56 identity = matched;
57 if (next == geojson)
58 return false;
59 geojson = next;
60 return true;
61 }
62
63 const std::string& data() const { return geojson; }
64
65private:
66 std::string identityProperty, identityPrefix, hoverFlag;
67 std::string featuresData = R"({"type":"FeatureCollection","features":[]})";
68 std::string identity;
69 std::string geojson = R"({"type":"FeatureCollection","features":[]})";
70};