From 9cea764a826160e286d9ae1e887511dd1cd5f4d7 Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Tue, 27 Aug 2024 16:47:21 +0200 Subject: [PATCH 1/8] Use JsValue instead of emsdk API --- libs/core/CMakeLists.txt | 7 +- .../erdblick/cesium-interface/object.h | 13 +++- libs/core/include/erdblick/sourcedata.hpp | 6 ++ libs/core/src/bindings.cpp | 7 +- libs/core/src/sourcedata.cpp | 64 +++++++++---------- libs/core/src/sourcedata.hpp | 5 -- 6 files changed, 59 insertions(+), 43 deletions(-) create mode 100644 libs/core/include/erdblick/sourcedata.hpp delete mode 100644 libs/core/src/sourcedata.hpp diff --git a/libs/core/CMakeLists.txt b/libs/core/CMakeLists.txt index be9726eb..5c435a7c 100644 --- a/libs/core/CMakeLists.txt +++ b/libs/core/CMakeLists.txt @@ -13,6 +13,7 @@ set(ERDBLICK_SOURCE_FILES include/erdblick/geometry.h include/erdblick/inspection.h include/erdblick/search.h + include/erdblick/sourcedata.hpp include/erdblick/cesium-interface/object.h include/erdblick/cesium-interface/primitive.h @@ -31,6 +32,7 @@ set(ERDBLICK_SOURCE_FILES src/geometry.cpp src/inspection.cpp src/search.cpp + src/sourcedata.cpp src/cesium-interface/object.cpp src/cesium-interface/primitive.cpp @@ -40,10 +42,7 @@ set(ERDBLICK_SOURCE_FILES ) if(${CMAKE_SYSTEM_NAME} STREQUAL "Emscripten") - list(APPEND ERDBLICK_SOURCE_FILES - src/bindings.cpp - src/sourcedata.hpp - src/sourcedata.cpp) + list(APPEND ERDBLICK_SOURCE_FILES src/bindings.cpp) add_executable(erdblick-core ${ERDBLICK_SOURCE_FILES}) target_compile_definitions(erdblick-core PUBLIC EMSCRIPTEN) # target_compile_options(erdblick-core PRIVATE -fwasm-exceptions) diff --git a/libs/core/include/erdblick/cesium-interface/object.h b/libs/core/include/erdblick/cesium-interface/object.h index adae853d..fa9811e6 100644 --- a/libs/core/include/erdblick/cesium-interface/object.h +++ b/libs/core/include/erdblick/cesium-interface/object.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include "mapget/model/info.h" @@ -32,6 +33,16 @@ struct always_false : std::false_type {}; */ struct JsValue { + template + static auto UnpackNativeValue(T&& v) + { + if constexpr (std::is_base_of_v>) { + return *v; + } else { + return std::forward(v); + } + } + /** * Construct an Object from a global JavaScript name using em::val::global. * If EMSCRIPTEN is not defined, simply returns an empty JSON object. @@ -185,7 +196,7 @@ template ReturnType JsValue::call(std::string const& methodName, Args... args) { #ifdef EMSCRIPTEN - return value_.call(methodName.c_str(), args...); + return value_.call(methodName.c_str(), UnpackNativeValue(args)...); #else // Record the method call in the mock object value_["methodCalls"].push_back({ diff --git a/libs/core/include/erdblick/sourcedata.hpp b/libs/core/include/erdblick/sourcedata.hpp new file mode 100644 index 00000000..adc7f406 --- /dev/null +++ b/libs/core/include/erdblick/sourcedata.hpp @@ -0,0 +1,6 @@ +#include + +#include "mapget/model/sourcedatalayer.h" +#include "cesium-interface/object.h" + +erdblick::JsValue tileSourceDataLayerToObject(const mapget::TileSourceDataLayer& layer); diff --git a/libs/core/src/bindings.cpp b/libs/core/src/bindings.cpp index c3148c5c..928c7700 100644 --- a/libs/core/src/bindings.cpp +++ b/libs/core/src/bindings.cpp @@ -5,6 +5,7 @@ #include "buffer.h" #include "cesium-interface/object.h" #include "mapget/model/info.h" +#include "mapget/model/sourcedatalayer.h" #include "simfil/model/nodes.h" #include "visualization.h" #include "parser.h" @@ -248,10 +249,12 @@ EMSCRIPTEN_BINDINGS(erdblick) em::class_("FeatureLayerStyle").constructor() .function("options", &FeatureLayerStyle::options, em::allow_raw_pointers()); + ////////// SourceDataAddressFormat em::enum_("SourceDataAddressFormat") .value("UNKNOWN", mapget::TileSourceDataLayer::SourceDataAddressFormat::Unknown) .value("BIT_RANGE", mapget::TileSourceDataLayer::SourceDataAddressFormat::BitRange); + ////////// TileSourceDataLayer em::class_("TileSourceDataLayer") .smart_ptr>( "std::shared_ptr") @@ -264,7 +267,9 @@ EMSCRIPTEN_BINDINGS(erdblick) return self.toJson().dump(2); })) .function( - "toObject", &tileSourceDataLayerToObject); + "toObject", std::function([](const mapget::TileSourceDataLayer& self) { + return *tileSourceDataLayerToObject(self); + })); ////////// Feature using FeaturePtr = mapget::model_ptr; diff --git a/libs/core/src/sourcedata.cpp b/libs/core/src/sourcedata.cpp index f09e6c75..c0257e03 100644 --- a/libs/core/src/sourcedata.cpp +++ b/libs/core/src/sourcedata.cpp @@ -11,39 +11,39 @@ * [{ data: [{key: "...", value: ...}, ...], children: [{ ... }] }, ...] * **/ -emscripten::val tileSourceDataLayerToObject(const mapget::TileSourceDataLayer& layer) { - namespace em = emscripten; +erdblick::JsValue tileSourceDataLayerToObject(const mapget::TileSourceDataLayer& layer) { + using namespace erdblick; using namespace mapget; using namespace simfil; const auto& strings = *layer.strings(); - std::function visit; - auto visitAtomic = [&](em::val&& key, const simfil::ModelNode& node) { - auto value = [&node]() -> em::val { + std::function visit; + auto visitAtomic = [&](JsValue&& key, const simfil::ModelNode& node) { + auto value = [&node]() -> JsValue { switch (node.type()) { case simfil::ValueType::Null: - return em::val::null(); + return JsValue(); case simfil::ValueType::Bool: - return em::val(std::get(node.value())); + return JsValue(std::get(node.value())); case simfil::ValueType::Int: - return em::val(std::get(node.value())); + return JsValue(std::get(node.value())); case simfil::ValueType::Float: - return em::val(std::get(node.value())); + return JsValue(std::get(node.value())); case simfil::ValueType::String: { auto v = node.value(); if (auto vv = std::get_if(&v)) - return em::val(*vv); + return JsValue(*vv); if (auto vv = std::get_if(&v)) - return em::val(std::string(*vv)); + return JsValue(std::string(*vv)); } default: - return em::val::null(); + return JsValue(); } }(); - auto res = em::val::object(); - auto data = em::val::object(); + auto res = JsValue::Dict(); + auto data = JsValue::Dict(); data.set("key", std::move(key)); data.set("value", std::move(value)); res.set("data", std::move(data)); @@ -51,17 +51,17 @@ emscripten::val tileSourceDataLayerToObject(const mapget::TileSourceDataLayer& l return res; }; - auto visitArray = [&](em::val&& key, const simfil::ModelNode& node) -> em::val { - auto res = em::val::object(); + auto visitArray = [&](JsValue&& key, const simfil::ModelNode& node) -> JsValue { + auto res = JsValue::Dict(); - auto data = em::val::object(); + auto data = JsValue::Dict(); data.set("key", std::move(key)); res.set("data", std::move(data)); - auto children = em::val::array(); + auto children = JsValue::List(); auto i = 0; for (const auto& item : node) { - children.call("push", visit(em::val(i++), *item)); + children.call("push", visit(JsValue(i++), *item)); } if (i > 0) @@ -72,35 +72,35 @@ emscripten::val tileSourceDataLayerToObject(const mapget::TileSourceDataLayer& l auto visitAddress = [&](const SourceDataAddress& addr) { if (layer.sourceDataAddressFormat() == mapget::TileSourceDataLayer::SourceDataAddressFormat::BitRange) { - auto res = em::val::object(); - res.set("offset", addr.bitOffset()); - res.set("size", addr.bitSize()); + auto res = JsValue::Dict(); + res.set("offset", JsValue(addr.bitOffset())); + res.set("size", JsValue(addr.bitSize())); return res; } else { - return em::val(addr.u64()); + return JsValue(addr.u64()); } }; - auto visitObject = [&](em::val&& key, const simfil::ModelNode& node) -> em::val { - auto res = em::val::object(); + auto visitObject = [&](JsValue&& key, const simfil::ModelNode& node) -> JsValue { + auto res = JsValue::Dict(); - auto data = em::val::object(); + auto data = JsValue::Dict(); data.set("key", std::move(key)); if (node.addr().column() == mapget::TileSourceDataLayer::Compound) { auto compound = layer.resolveCompound(*ModelNode::Ptr::make(layer.shared_from_this(), node.addr())); data.set("address", visitAddress(compound->sourceDataAddress())); - data.set("type", std::string(compound->schemaName())); + data.set("type", JsValue(std::string(compound->schemaName()))); } res.set("data", std::move(data)); - auto children = em::val::array(); + auto children = JsValue::List(); for (const auto& [field, v] : node.fields()) { if (auto k = strings.resolve(field); k && v) { - children.call("push", visit(em::val(k->data()), *v)); + children.call("push", visit(JsValue(k->data()), *v)); } } @@ -110,7 +110,7 @@ emscripten::val tileSourceDataLayerToObject(const mapget::TileSourceDataLayer& l return res; }; - visit = [&](em::val&& key, const simfil::ModelNode& node) -> em::val { + visit = [&](JsValue&& key, const simfil::ModelNode& node) -> JsValue { switch (node.type()) { case simfil::ValueType::Array: return visitArray(std::move(key), node); @@ -122,7 +122,7 @@ emscripten::val tileSourceDataLayerToObject(const mapget::TileSourceDataLayer& l }; if (layer.numRoots() == 0) - return em::val::object(); + return JsValue::Dict(); - return visit(em::val("root"), *layer.root(0)); + return visit(JsValue("root"), *layer.root(0)); } diff --git a/libs/core/src/sourcedata.hpp b/libs/core/src/sourcedata.hpp deleted file mode 100644 index 44180379..00000000 --- a/libs/core/src/sourcedata.hpp +++ /dev/null @@ -1,5 +0,0 @@ -#include - -#include "mapget/model/sourcedatalayer.h" - -emscripten::val tileSourceDataLayerToObject(const mapget::TileSourceDataLayer& layer); From b5c1de655827aaa69b5c60b52e54f7122f8150b2 Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Tue, 27 Aug 2024 18:31:30 +0200 Subject: [PATCH 2/8] Add button to switch between SourceData layers --- erdblick_app/app/map.panel.component.ts | 70 ++++++++++--------- erdblick_app/app/map.service.ts | 4 -- .../app/sourcedata.panel.component.ts | 47 ++++++++++--- erdblick_app/styles.scss | 8 +++ 4 files changed, 82 insertions(+), 47 deletions(-) diff --git a/erdblick_app/app/map.panel.component.ts b/erdblick_app/app/map.panel.component.ts index 7ff6e5a8..ff9da045 100644 --- a/erdblick_app/app/map.panel.component.ts +++ b/erdblick_app/app/map.panel.component.ts @@ -39,41 +39,43 @@ import {Menu} from "primeng/menu"; {{ mapItem.key }} -
-
- more_vert - - - -
-
- - {{ mapLayer.value.tileBorders ? 'select_all' : 'deselect' }} - - - loupe - - - +
+
+
+ more_vert + + + +
+
+ + {{ mapLayer.value.tileBorders ? 'select_all' : 'deselect' }} + + + loupe + + + +
+
-
diff --git a/erdblick_app/app/map.service.ts b/erdblick_app/app/map.service.ts index dc1b7c21..8e4e790d 100644 --- a/erdblick_app/app/map.service.ts +++ b/erdblick_app/app/map.service.ts @@ -265,10 +265,6 @@ export class MapService { let maps = new Map(result.filter(m => !m.addOn).map(mapInfo => { let layers = new Map(); for (let [layerId, layerInfo] of Object.entries(mapInfo.layers)) { - // Filter out source-data layers - if (layerId.startsWith("SourceData-")) - continue; - [layerInfo.visible, layerInfo.level, layerInfo.tileBorders] = this.parameterService.mapLayerConfig(mapInfo.mapId, layerId, 13); mapLayerLevels.push([ mapInfo.mapId + '/' + layerId, diff --git a/erdblick_app/app/sourcedata.panel.component.ts b/erdblick_app/app/sourcedata.panel.component.ts index 4ffa937f..a07d6ca7 100644 --- a/erdblick_app/app/sourcedata.panel.component.ts +++ b/erdblick_app/app/sourcedata.panel.component.ts @@ -1,9 +1,11 @@ import {Component, OnInit, Input, ViewChild} from "@angular/core"; import {TreeTableNode} from "primeng/api"; import {InspectionService, SelectedSourceData} from "./inspection.service"; +import {MapService} from "./map.service"; import {coreLib} from "./wasm"; import {SourceDataAddressFormat} from "build/libs/core/erdblick-core"; import {TreeTable} from "primeng/treetable"; +import {Menu} from "primeng/menu"; @Component({ selector: 'sourcedata-panel', @@ -39,6 +41,7 @@ import {TreeTable} from "primeng/treetable"; /> + @@ -77,14 +80,15 @@ import {TreeTable} from "primeng/treetable"; + + ` }) export class SourceDataPanelComponent implements OnInit { - @Input() - sourceData!: SelectedSourceData; + @Input() sourceData!: SelectedSourceData; - @ViewChild('tt') - table!: TreeTable; + @ViewChild('tt') table!: TreeTable; + @ViewChild('layerListMenu') layerListMenu!: Menu; treeData: TreeTableNode[] = []; filterFields = [ @@ -92,10 +96,10 @@ export class SourceDataPanelComponent implements OnInit { "value" ]; columns = [ - { key: "key", header: "Key", width: '180px', transform: (v: any) => v }, - { key: "value", header: "Value", width: '0*', transform: (v: any) => v }, - { key: "address", header: "Address", width: '80px', transform: this.addressFormatter }, - { key: "type", header: "Type", width: 'auto', transform: this.schemaTypeURLFormatter }, + { key: "key", header: "Key", width: '0*', transform: (v: any) => v }, + { key: "value", header: "Value", width: '0*', transform: (v: any) => v }, + { key: "address", header: "Address", width: '80px', transform: this.addressFormatter }, + { key: "type", header: "Type", width: 'auto', transform: this.schemaTypeURLFormatter }, ] loading: boolean = true; @@ -104,7 +108,9 @@ export class SourceDataPanelComponent implements OnInit { isExpanded = false; filterString = ""; - constructor(private inspectionService: InspectionService) {} + layerList: any[] = []; + + constructor(private inspectionService: InspectionService, public mapService: MapService) {} ngOnInit(): void { this.inspectionService.loadSourceDataLayer(this.sourceData.tileId, this.sourceData.layerId, this.sourceData.mapId) @@ -128,6 +134,29 @@ export class SourceDataPanelComponent implements OnInit { .finally(() => { this.loading = false; }); + + this.mapService.maps.subscribe(maps => { + const map = maps.get(this.sourceData.mapId); + if (map) { + this.layerList = Array.from(map.layers.values()) + .filter(item => item.layerId.startsWith("SourceData-")) + .map(item => { + return { + label: item.layerId, + disabled: item.layerId === this.sourceData.layerId, + command: () => { + let sourceData = {...this.sourceData}; + sourceData.layerId = item.layerId; + sourceData.address = BigInt(0); + + this.inspectionService.selectedSourceData.next(sourceData); + }, + }; + }); + } else { + this.layerList = []; + } + }); } /** diff --git a/erdblick_app/styles.scss b/erdblick_app/styles.scss index fba0eae0..eb0d3b6a 100644 --- a/erdblick_app/styles.scss +++ b/erdblick_app/styles.scss @@ -129,6 +129,14 @@ body { .filter-container { width: 100%; + display: flex; + gap: 4px; + justify-content: center; + + .p-button { + width: 32px; + height: 32px; + } } .filter-input { From d5d589c57c2e477fcb63be71fbf2fb006f46bcd8 Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Tue, 27 Aug 2024 18:36:52 +0200 Subject: [PATCH 3/8] Fix JsValues call forwarding --- libs/core/include/erdblick/cesium-interface/object.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libs/core/include/erdblick/cesium-interface/object.h b/libs/core/include/erdblick/cesium-interface/object.h index fa9811e6..75c28cdf 100644 --- a/libs/core/include/erdblick/cesium-interface/object.h +++ b/libs/core/include/erdblick/cesium-interface/object.h @@ -201,7 +201,7 @@ ReturnType JsValue::call(std::string const& methodName, Args... args) // Record the method call in the mock object value_["methodCalls"].push_back({ {"methodName", methodName}, - {"arguments", {args...}} // This assumes Args are convertible to nlohmann::json + {"arguments", {UnpackNativeValue(args)...}} // This assumes Args are convertible to nlohmann::json }); return ReturnType(); // default-constructed value #endif From d46d06d86b8a4e88e7941f3d79e6e0d4ccf59145 Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Tue, 27 Aug 2024 18:59:41 +0200 Subject: [PATCH 4/8] Review fixes --- erdblick_app/app/highlight.pipe.ts | 4 +-- .../app/inspection.panel.component.ts | 4 +-- erdblick_app/app/inspection.service.ts | 19 +++++------ erdblick_app/app/parameters.service.ts | 2 +- .../app/sourcedata.panel.component.ts | 32 ++++++++----------- .../app/treetablefilter-patch.directive.ts | 8 ++--- 6 files changed, 30 insertions(+), 39 deletions(-) diff --git a/erdblick_app/app/highlight.pipe.ts b/erdblick_app/app/highlight.pipe.ts index 5b0b972f..cf1664a2 100644 --- a/erdblick_app/app/highlight.pipe.ts +++ b/erdblick_app/app/highlight.pipe.ts @@ -9,7 +9,7 @@ export class HighlightSearch implements PipeTransform { return value; } - let re = new RegExp(String(args).replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi'); + const re = new RegExp(String(args).replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'gi'); return String(value).replace(re, '$&'); } -} \ No newline at end of file +} diff --git a/erdblick_app/app/inspection.panel.component.ts b/erdblick_app/app/inspection.panel.component.ts index 334055fd..b33982a8 100644 --- a/erdblick_app/app/inspection.panel.component.ts +++ b/erdblick_app/app/inspection.panel.component.ts @@ -55,7 +55,7 @@ interface InspectorTab { }`, ] }) -export class InspectionPanelComponent implements OnInit +export class InspectionPanelComponent { title = ""; tabs: InspectorTab[] = []; @@ -86,8 +86,6 @@ export class InspectionPanelComponent implements OnInit }) } - ngOnInit(): void {} - reset() { /* We always keep the first tab, which is a feature inspector. */ this.setTab(0); diff --git a/erdblick_app/app/inspection.service.ts b/erdblick_app/app/inspection.service.ts index 2130aa46..883e932f 100644 --- a/erdblick_app/app/inspection.service.ts +++ b/erdblick_app/app/inspection.service.ts @@ -32,7 +32,7 @@ export interface SelectedSourceData { export function selectedSourceDataEqualTo(a: SelectedSourceData | null, b: SelectedSourceData | null) { if (!a || !b) return false; - return (a == b || (a.mapId == b.mapId && a.tileId == b.tileId && a.layerId == b.layerId && a.address == b.address && a.featureId == b.featureId)); + return (a === b || (a.mapId === b.mapId && a.tileId === b.tileId && a.layerId === b.layerId && a.address === b.address && a.featureId === b.featureId)); } @Injectable({providedIn: 'root'}) @@ -174,16 +174,13 @@ export class InspectionService { async loadSourceDataLayer(tileId: number, layerId: string, mapId: string) : Promise { console.log(`Loading SourceDataLayer layerId=${layerId} tileId=${tileId}`); - let requests = [{ - mapId: mapId, - layerId: layerId, - tileIds: [tileId] - }]; - - let tileParser = new coreLib.TileLayerParser(); - - let newRequestBody = JSON.stringify({ - requests: requests + const tileParser = new coreLib.TileLayerParser(); + const newRequestBody = JSON.stringify({ + requests: [{ + mapId: mapId, + layerId: layerId, + tileIds: [tileId] + }] }); let layer: TileSourceDataLayer | undefined; diff --git a/erdblick_app/app/parameters.service.ts b/erdblick_app/app/parameters.service.ts index 55c987f6..1ef8ce2d 100644 --- a/erdblick_app/app/parameters.service.ts +++ b/erdblick_app/app/parameters.service.ts @@ -167,7 +167,7 @@ export class ParametersService { } }); - constructor(public router: Router /*, private inspectionService: InspectionService*/) { + constructor(public router: Router) { let parameters = this.loadSavedParameters(); this.parameters = new BehaviorSubject(parameters!); this.saveParameters(); diff --git a/erdblick_app/app/sourcedata.panel.component.ts b/erdblick_app/app/sourcedata.panel.component.ts index a07d6ca7..5f826cdc 100644 --- a/erdblick_app/app/sourcedata.panel.component.ts +++ b/erdblick_app/app/sourcedata.panel.component.ts @@ -115,7 +115,7 @@ export class SourceDataPanelComponent implements OnInit { ngOnInit(): void { this.inspectionService.loadSourceDataLayer(this.sourceData.tileId, this.sourceData.layerId, this.sourceData.mapId) .then(layer => { - let root = layer.toObject() + const root = layer.toObject() this.addressFormat = layer.addressFormat(); layer.delete(); @@ -170,7 +170,7 @@ export class SourceDataPanelComponent implements OnInit { this.treeData = []; this.errorMessage = message; - console.error(this.errorMessage); + console.error("Error while processing SourceData tree:", this.errorMessage) } /** @@ -187,23 +187,19 @@ export class SourceDataPanelComponent implements OnInit { const prefix = "https://developer.nds.live/schema/"; - let match = schema.match(/^nds\.(([^.]+\.)+)v(\d{4}_\d{2})((\.[^.]*)+)/); + const match = schema.match(/^nds\.(([^.]+\.)+)v(\d{4}_\d{2})((\.[^.]*)+)/); if (!match || match.length <= 4) return schema; // Sub-namespaces in front of the version get joined by "-". Names past the version get joined by "/" - let url = + const url = match[1].replace(/^(.*)\.$/, "$1/").replaceAll(".", "-") + match[3].replaceAll("_", ".") + match[4].replaceAll(".", "/"); return `${schema}`; } - addressFormatter(address?: any) { - if (!address) { - return address; - } - + addressFormatter(address?: any): string { if (typeof address === 'object') { return `${address.offset}:${address.size}` } else { @@ -212,10 +208,9 @@ export class SourceDataPanelComponent implements OnInit { } selectItemWithAddress(address: bigint) { - let searchAddress: any = address; let addressInRange: any; if (this.addressFormat == coreLib.SourceDataAddressFormat.BIT_RANGE) { - searchAddress = { + const searchAddress = { offset: address >> BigInt(32) & BigInt(0xFFFFFFFF), size: address & BigInt(0xFFFFFFFF), } @@ -223,12 +218,15 @@ export class SourceDataPanelComponent implements OnInit { const addressLow = typeof searchAddress === 'object' ? searchAddress['offset'] : searchAddress; const addressHigh = addressLow + (typeof searchAddress === 'object' ? searchAddress['size'] : searchAddress); - addressInRange = (addr: any) => { - return addr.offset >= addressLow && addr.offset + addr.size <= addressHigh && (addr.size != 0 || addressLow == addressHigh); + addressInRange = (address: any) => { + return address.offset >= addressLow && + address.offset + address.size <= addressHigh && + (address.size != 0 || addressLow == addressHigh); } } else { - addressInRange = (addr: any) => { - return addr == searchAddress; + const searchAddress = address; + addressInRange = (address: any) => { + return address == searchAddress; } } @@ -244,8 +242,7 @@ export class SourceDataPanelComponent implements OnInit { node.data.styleClass = "highlight"; } - const address = node.data.address; - if (address && addressInRange(address)) { + if (node.data.address && addressInRange(node.data.address)) { highlight = true; if (!firstHighlightedItemIndex) @@ -262,7 +259,6 @@ export class SourceDataPanelComponent implements OnInit { } }; - console.log(`Highlighting item with address`, searchAddress); this.treeData.forEach((item: TreeTableNode, index) => { select(item, [], false, index); }); diff --git a/erdblick_app/app/treetablefilter-patch.directive.ts b/erdblick_app/app/treetablefilter-patch.directive.ts index 76b79ada..260c5964 100644 --- a/erdblick_app/app/treetablefilter-patch.directive.ts +++ b/erdblick_app/app/treetablefilter-patch.directive.ts @@ -25,11 +25,11 @@ export class TreeTableFilterPatchDirective implements AfterContentInit { if (node) { let matched = false; if (node.children) { - let childNodes = [...node.children].map(node => { return { ...node }; }); + const children = node.children.map(node => { return { ...node }; }); node.children = []; let hadMatchingLeaf = false; - for (let childNode of childNodes) { + for (const childNode of children) { if (this.tt.isFilterMatched(childNode, paramsWithoutNode)) { matched = true; hadMatchingLeaf = hadMatchingLeaf || this.tt.isNodeLeaf(childNode); @@ -41,7 +41,7 @@ export class TreeTableFilterPatchDirective implements AfterContentInit { // If we had a matching leaf node, add all leaf nodes. // Since we are in strict mode, if no child matched, add all if (hadMatchingLeaf || !matched) { - node.children = childNodes; + node.children = children; } } @@ -53,4 +53,4 @@ export class TreeTableFilterPatchDirective implements AfterContentInit { return false; } } -} \ No newline at end of file +} From 77ae4ea9cdd8efd698f4894e3ff3e7f1a7865625 Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Wed, 28 Aug 2024 10:05:34 +0200 Subject: [PATCH 5/8] Show human readable layer name --- .../app/inspection.panel.component.ts | 2 +- .../app/sourcedata.panel.component.ts | 69 ++++++++++++------- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/erdblick_app/app/inspection.panel.component.ts b/erdblick_app/app/inspection.panel.component.ts index b33982a8..0ceb8c77 100644 --- a/erdblick_app/app/inspection.panel.component.ts +++ b/erdblick_app/app/inspection.panel.component.ts @@ -115,7 +115,7 @@ export class InspectionPanelComponent pushSourceDataInspector(data: SelectedSourceData) { let tab = { - title: data.layerId, + title: SourceDataPanelComponent.layerNameForLayerId(data.layerId), icon: "pi-database", component: SourceDataPanelComponent, inputs: { diff --git a/erdblick_app/app/sourcedata.panel.component.ts b/erdblick_app/app/sourcedata.panel.component.ts index 5f826cdc..1ea68835 100644 --- a/erdblick_app/app/sourcedata.panel.component.ts +++ b/erdblick_app/app/sourcedata.panel.component.ts @@ -41,7 +41,7 @@ import {Menu} from "primeng/menu"; /> - + @@ -81,14 +81,14 @@ import {Menu} from "primeng/menu"; - + ` }) export class SourceDataPanelComponent implements OnInit { @Input() sourceData!: SelectedSourceData; @ViewChild('tt') table!: TreeTable; - @ViewChild('layerListMenu') layerListMenu!: Menu; + @ViewChild('layerMenuItemsMenu') layerListMenu!: Menu; treeData: TreeTableNode[] = []; filterFields = [ @@ -96,19 +96,31 @@ export class SourceDataPanelComponent implements OnInit { "value" ]; columns = [ - { key: "key", header: "Key", width: '0*', transform: (v: any) => v }, - { key: "value", header: "Value", width: '0*', transform: (v: any) => v }, - { key: "address", header: "Address", width: '80px', transform: this.addressFormatter }, - { key: "type", header: "Type", width: 'auto', transform: this.schemaTypeURLFormatter }, + { key: "key", header: "Key", width: '0*', transform: (v: any) => v }, + { key: "value", header: "Value", width: '0*', transform: (v: any) => v }, + { key: "address", header: "Address", width: '100px', transform: this.addressFormatter }, + { key: "type", header: "Type", width: 'auto', transform: this.schemaTypeURLFormatter }, ] loading: boolean = true; + filterString = ""; addressFormat: SourceDataAddressFormat = coreLib.SourceDataAddressFormat.BIT_RANGE; errorMessage = ""; isExpanded = false; - filterString = ""; - layerList: any[] = []; + layerMenuItems: any[] = []; + + /** + * Returns a human readable layer name for a layer id. + * + * @param layerId Layer id to get the name for + */ + public static layerNameForLayerId(layerId: string) { + const match = layerId.match(/^SourceData-([^.]+\.)*(.*)-([\d]+)/); + if (match) + return `${match[2]}.${match[3]}`; + return layerId; + } constructor(private inspectionService: InspectionService, public mapService: MapService) {} @@ -138,23 +150,28 @@ export class SourceDataPanelComponent implements OnInit { this.mapService.maps.subscribe(maps => { const map = maps.get(this.sourceData.mapId); if (map) { - this.layerList = Array.from(map.layers.values()) - .filter(item => item.layerId.startsWith("SourceData-")) - .map(item => { - return { - label: item.layerId, - disabled: item.layerId === this.sourceData.layerId, - command: () => { - let sourceData = {...this.sourceData}; - sourceData.layerId = item.layerId; - sourceData.address = BigInt(0); - - this.inspectionService.selectedSourceData.next(sourceData); - }, - }; - }); + this.layerMenuItems = [ + { + label: "Switch Layer", + items: Array.from(map.layers.values()) + .filter(item => item.layerId.startsWith("SourceData-")) + .map(item => { + return { + label: SourceDataPanelComponent.layerNameForLayerId(item.layerId), + disabled: item.layerId === this.sourceData.layerId, + command: () => { + let sourceData = {...this.sourceData}; + sourceData.layerId = item.layerId; + sourceData.address = BigInt(0); + + this.inspectionService.selectedSourceData.next(sourceData); + }, + }; + }), + }, + ]; } else { - this.layerList = []; + this.layerMenuItems = []; } }); } @@ -170,7 +187,7 @@ export class SourceDataPanelComponent implements OnInit { this.treeData = []; this.errorMessage = message; - console.error("Error while processing SourceData tree:", this.errorMessage) + console.error("Error while processing SourceData tree:", this.errorMessage); } /** From 3d701d12720c0f8e91fa7d97be10ed5d28ba98c6 Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Wed, 28 Aug 2024 11:14:36 +0200 Subject: [PATCH 6/8] Fix address formatting --- erdblick_app/app/sourcedata.panel.component.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/erdblick_app/app/sourcedata.panel.component.ts b/erdblick_app/app/sourcedata.panel.component.ts index 1ea68835..ee4a217a 100644 --- a/erdblick_app/app/sourcedata.panel.component.ts +++ b/erdblick_app/app/sourcedata.panel.component.ts @@ -219,8 +219,10 @@ export class SourceDataPanelComponent implements OnInit { addressFormatter(address?: any): string { if (typeof address === 'object') { return `${address.offset}:${address.size}` - } else { + } else if (address) { return `${address}` + } else { + return ''; } } From 955bafecc11069f93d47b157198bd05ed24e9632 Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Thu, 29 Aug 2024 15:17:24 +0200 Subject: [PATCH 7/8] Fix SourceData Layer Filtering --- erdblick_app/app/map.panel.component.ts | 2 +- erdblick_app/app/map.service.ts | 4 ++-- erdblick_app/app/sourcedata.panel.component.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/erdblick_app/app/map.panel.component.ts b/erdblick_app/app/map.panel.component.ts index ff9da045..b0bc228d 100644 --- a/erdblick_app/app/map.panel.component.ts +++ b/erdblick_app/app/map.panel.component.ts @@ -40,7 +40,7 @@ import {Menu} from "primeng/menu"; {{ mapItem.key }}
-
+
; featureTypes: Array<{name: string, uniqueIdCompositions: Array}>; layerId: string; - type: number; + type: string; version: {major: number, minor: number, patch: number}; zoomLevels: Array; level: number; @@ -295,7 +295,7 @@ export class MapService { const layer = mapItem.layers.get(layerId); if (layer) { - if (layer.type == coreLib.LayerType.SOURCEDATA.value) + if (layer.type == "SourceData") return false; return layer.visible; } diff --git a/erdblick_app/app/sourcedata.panel.component.ts b/erdblick_app/app/sourcedata.panel.component.ts index ee4a217a..3214d194 100644 --- a/erdblick_app/app/sourcedata.panel.component.ts +++ b/erdblick_app/app/sourcedata.panel.component.ts @@ -154,7 +154,7 @@ export class SourceDataPanelComponent implements OnInit { { label: "Switch Layer", items: Array.from(map.layers.values()) - .filter(item => item.layerId.startsWith("SourceData-")) + .filter(item => item.type == "SourceData") .map(item => { return { label: SourceDataPanelComponent.layerNameForLayerId(item.layerId), From 5cd4857bf22db25454997c0b3abbe0542aa524d3 Mon Sep 17 00:00:00 2001 From: Johannes Wolf Date: Thu, 29 Aug 2024 15:18:55 +0200 Subject: [PATCH 8/8] Move SourceData conversion to namespace --- libs/core/include/erdblick/sourcedata.hpp | 13 +++++++++++++ libs/core/src/sourcedata.cpp | 13 +++++-------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/libs/core/include/erdblick/sourcedata.hpp b/libs/core/include/erdblick/sourcedata.hpp index adc7f406..a955fddb 100644 --- a/libs/core/include/erdblick/sourcedata.hpp +++ b/libs/core/include/erdblick/sourcedata.hpp @@ -3,4 +3,17 @@ #include "mapget/model/sourcedatalayer.h" #include "cesium-interface/object.h" +namespace erdblick +{ + +/** + * Convert a SourceDataLayar hierarchy to a tree model compatible + * structure. + * + * Layout: + * [{ data: [{key: "...", value: ...}, ...], children: [{ ... }] }, ...] + * + **/ erdblick::JsValue tileSourceDataLayerToObject(const mapget::TileSourceDataLayer& layer); + +} diff --git a/libs/core/src/sourcedata.cpp b/libs/core/src/sourcedata.cpp index c0257e03..24132b92 100644 --- a/libs/core/src/sourcedata.cpp +++ b/libs/core/src/sourcedata.cpp @@ -3,14 +3,9 @@ #include "mapget/model/sourcedatalayer.h" #include "mapget/model/sourcedata.h" -/** - * Convert a SourceDataLayar hierarchy to a tree model compatible - * structure. - * - * Layout: - * [{ data: [{key: "...", value: ...}, ...], children: [{ ... }] }, ...] - * - **/ +namespace erdblick +{ + erdblick::JsValue tileSourceDataLayerToObject(const mapget::TileSourceDataLayer& layer) { using namespace erdblick; using namespace mapget; @@ -126,3 +121,5 @@ erdblick::JsValue tileSourceDataLayerToObject(const mapget::TileSourceDataLayer& return visit(JsValue("root"), *layer.root(0)); } + +}