MapComplete/src/Models/ThemeViewState/WithSelectedElementState.ts

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

96 lines
3.2 KiB
TypeScript
Raw Normal View History

import { UserMapFeatureswitchState } from "./UserMapFeatureswitchState"
import ThemeConfig from "../ThemeConfig/ThemeConfig"
import { UIEventSource } from "../../Logic/UIEventSource"
import { Feature } from "geojson"
import Zoomcontrol from "../../UI/Zoomcontrol"
import { GeoOperations } from "../../Logic/GeoOperations"
import { GeocodeResult } from "../../Logic/Search/GeocodingProvider"
/**
* The state interactions with a selected element, but is blind to loading elements
*
*
* No GUI stuff
*/
export class WithSelectedElementState extends UserMapFeatureswitchState {
readonly selectedElement: UIEventSource<Feature>
constructor(theme: ThemeConfig) {
2025-01-28 15:42:34 +01:00
const selectedElement = new UIEventSource<Feature | undefined>(
undefined,
"Selected element"
)
super(theme, selectedElement)
this.selectedElement = selectedElement
this.selectedElement.addCallback((selected) => {
if (selected === undefined) {
Zoomcontrol.resetzoom()
}
})
this.mapProperties.lastClickLocation.addCallbackD((lastClick) => {
if (lastClick.mode !== "left") {
return
}
const nearestFeature = lastClick.nearestFeature
this.setSelectedElement(nearestFeature)
})
// Add the selected element to the recently visited history
this.selectedElement.addCallbackD((selected) => {
const [osm_type, osm_id] = selected.properties.id.split("/")
const [lon, lat] = GeoOperations.centerpointCoordinates(selected)
const layer = this.theme.getMatchingLayer(selected.properties)
2025-05-12 12:47:39 +02:00
if (!layer) {
return
}
if (!layer?.isNormal()) {
return
}
const nameOptions = [
selected?.properties?.name,
selected?.properties?.alt_name,
selected?.properties?.local_name,
2025-02-16 01:34:54 +01:00
layer?.title?.GetRenderValue(selected?.properties ?? {})?.txt,
selected.properties.display_name,
2025-01-28 15:42:34 +01:00
selected.properties.id,
]
const r = <GeocodeResult>{
feature: selected,
display_name: nameOptions.find((opt) => opt !== undefined),
osm_id,
osm_type,
lon,
2025-01-28 15:42:34 +01:00
lat,
}
this.userRelatedState.recentlyVisitedSearch.add(r)
})
}
protected setSelectedElement(feature: Feature) {
if (!feature) {
this.selectedElement.setData(undefined)
return
}
const layer = this.theme.getMatchingLayer(feature?.properties)
if (layer?.title === undefined) {
2025-05-03 23:48:35 +02:00
console.log(
"Not selecting feature",
feature,
": no title (or no matching layer) found, unselectable element"
)
return
}
const current = this.selectedElement.data
if (
current?.properties?.id !== undefined &&
current.properties.id === feature?.properties?.id
) {
return // already set
}
this.selectedElement.setData(feature)
}
}