forked from MapComplete/MapComplete
refactoring: more state splitting, basic layoutFeatureSource
This commit is contained in:
parent
8e2f04c0d0
commit
b94a8f5745
54 changed files with 1067 additions and 1969 deletions
107
Logic/FeatureSource/Actors/FeaturePropertiesStore.ts
Normal file
107
Logic/FeatureSource/Actors/FeaturePropertiesStore.ts
Normal file
|
@ -0,0 +1,107 @@
|
|||
import FeatureSource, { IndexedFeatureSource } from "../FeatureSource"
|
||||
import { UIEventSource } from "../../UIEventSource"
|
||||
|
||||
/**
|
||||
* Constructs a UIEventStore for the properties of every Feature, indexed by id
|
||||
*/
|
||||
export default class FeaturePropertiesStore {
|
||||
private readonly _source: FeatureSource & IndexedFeatureSource
|
||||
private readonly _elements = new Map<string, UIEventSource<any>>()
|
||||
|
||||
constructor(source: FeatureSource & IndexedFeatureSource) {
|
||||
this._source = source
|
||||
const self = this
|
||||
source.features.addCallbackAndRunD((features) => {
|
||||
for (const feature of features) {
|
||||
const id = feature.properties.id
|
||||
if (id === undefined) {
|
||||
console.trace("Error: feature without ID:", feature)
|
||||
throw "Error: feature without ID"
|
||||
}
|
||||
|
||||
const source = self._elements.get(id)
|
||||
if (source === undefined) {
|
||||
self._elements.set(id, new UIEventSource<any>(feature.properties))
|
||||
continue
|
||||
}
|
||||
|
||||
if (source.data === feature.properties) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Update the tags in the old store and link them
|
||||
const changeMade = FeaturePropertiesStore.mergeTags(source.data, feature.properties)
|
||||
feature.properties = source.data
|
||||
if (changeMade) {
|
||||
source.ping()
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
public getStore(id: string): UIEventSource<Record<string, string>> {
|
||||
return this._elements.get(id)
|
||||
}
|
||||
|
||||
/**
|
||||
* Overwrites the tags of the old properties object, returns true if a change was made.
|
||||
* Metatags are overriden if they are in the new properties, but not removed
|
||||
* @param oldProperties
|
||||
* @param newProperties
|
||||
* @private
|
||||
*/
|
||||
private static mergeTags(
|
||||
oldProperties: Record<string, any>,
|
||||
newProperties: Record<string, any>
|
||||
): boolean {
|
||||
let changeMade = false
|
||||
|
||||
for (const oldPropertiesKey in oldProperties) {
|
||||
// Delete properties from the old record if it is not in the new store anymore
|
||||
if (oldPropertiesKey.startsWith("_")) {
|
||||
continue
|
||||
}
|
||||
if (newProperties[oldPropertiesKey] === undefined) {
|
||||
changeMade = true
|
||||
delete oldProperties[oldPropertiesKey]
|
||||
}
|
||||
}
|
||||
|
||||
// Copy all properties from the new record into the old
|
||||
for (const newPropertiesKey in newProperties) {
|
||||
const v = newProperties[newPropertiesKey]
|
||||
if (oldProperties[newPropertiesKey] !== v) {
|
||||
oldProperties[newPropertiesKey] = v
|
||||
changeMade = true
|
||||
}
|
||||
}
|
||||
|
||||
return changeMade
|
||||
}
|
||||
|
||||
addAlias(oldId: string, newId: string): void {
|
||||
if (newId === undefined) {
|
||||
// We removed the node/way/relation with type 'type' and id 'oldId' on openstreetmap!
|
||||
const element = this._elements.get(oldId)
|
||||
element.data._deleted = "yes"
|
||||
element.ping()
|
||||
return
|
||||
}
|
||||
|
||||
if (oldId == newId) {
|
||||
return
|
||||
}
|
||||
const element = this._elements.get(oldId)
|
||||
if (element === undefined) {
|
||||
// Element to rewrite not found, probably a node or relation that is not rendered
|
||||
return
|
||||
}
|
||||
element.data.id = newId
|
||||
this._elements.set(newId, element)
|
||||
element.ping()
|
||||
}
|
||||
|
||||
has(id: string) {
|
||||
return this._elements.has(id)
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
import { FeatureSourceForLayer, Tiled } from "../FeatureSource"
|
||||
import MetaTagging from "../../MetaTagging"
|
||||
import { ElementStorage } from "../../ElementStorage"
|
||||
import { ExtraFuncParams } from "../../ExtraFunctions"
|
||||
import FeaturePipeline from "../FeaturePipeline"
|
||||
import { BBox } from "../../BBox"
|
||||
|
@ -39,7 +38,6 @@ class MetatagUpdater {
|
|||
}
|
||||
return featurePipeline.GetFeaturesWithin(layerId, bbox)
|
||||
},
|
||||
memberships: featurePipeline.relationTracker,
|
||||
}
|
||||
this.isDirty.stabilized(100).addCallback((dirty) => {
|
||||
if (dirty) {
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
import FeatureSource from "../FeatureSource";
|
||||
import { Store } from "../../UIEventSource";
|
||||
import { ElementStorage } from "../../ElementStorage";
|
||||
import { Feature } from "geojson";
|
||||
|
||||
/**
|
||||
* Makes sure that every feature is added to the ElementsStorage, so that the tags-eventsource can be retrieved
|
||||
*/
|
||||
export default class RegisteringAllFromFeatureSourceActor {
|
||||
public readonly features: Store<Feature[]>
|
||||
|
||||
constructor(source: FeatureSource, allElements: ElementStorage) {
|
||||
this.features = source.features
|
||||
this.features.addCallbackAndRunD((features) => {
|
||||
for (const feature of features) {
|
||||
allElements.addOrGetElement(<any> feature)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue