2025-01-23 05:01:55 +01:00
|
|
|
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"
|
|
|
|
|
)
|
2025-01-23 05:01:55 +01:00
|
|
|
super(theme, selectedElement)
|
|
|
|
|
this.selectedElement = selectedElement
|
|
|
|
|
this.selectedElement.addCallback((selected) => {
|
|
|
|
|
if (selected === undefined) {
|
|
|
|
|
Zoomcontrol.resetzoom()
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
this.mapProperties.lastClickLocation.addCallbackD((lastClick) => {
|
2025-01-23 12:30:42 +01:00
|
|
|
if (lastClick.mode !== "left") {
|
2025-01-23 05:01:55 +01:00
|
|
|
return
|
|
|
|
|
}
|
2025-04-23 10:43:07 +02:00
|
|
|
const nearestFeature = lastClick.nearestFeature
|
|
|
|
|
this.setSelectedElement(nearestFeature)
|
2025-01-23 05:01:55 +01:00
|
|
|
})
|
|
|
|
|
|
|
|
|
|
// 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()) {
|
2025-04-01 03:07:00 +02:00
|
|
|
return
|
|
|
|
|
}
|
2025-01-23 05:01:55 +01:00
|
|
|
|
|
|
|
|
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,
|
2025-01-23 05:01:55 +01:00
|
|
|
selected.properties.display_name,
|
2025-01-28 15:42:34 +01:00
|
|
|
selected.properties.id,
|
2025-01-23 05:01:55 +01:00
|
|
|
]
|
|
|
|
|
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,
|
2025-01-23 05:01:55 +01:00
|
|
|
}
|
|
|
|
|
this.userRelatedState.recentlyVisitedSearch.add(r)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected setSelectedElement(feature: Feature) {
|
2025-04-23 10:43:07 +02:00
|
|
|
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"
|
|
|
|
|
)
|
2025-04-23 10:43:07 +02:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-23 05:01:55 +01:00
|
|
|
const current = this.selectedElement.data
|
|
|
|
|
if (
|
|
|
|
|
current?.properties?.id !== undefined &&
|
2025-01-23 12:30:42 +01:00
|
|
|
current.properties.id === feature?.properties?.id
|
2025-01-23 05:01:55 +01:00
|
|
|
) {
|
|
|
|
|
return // already set
|
|
|
|
|
}
|
|
|
|
|
this.selectedElement.setData(feature)
|
|
|
|
|
}
|
|
|
|
|
}
|