| 
									
										
										
										
											2023-03-25 02:48:24 +01:00
										 |  |  | import { UIEventSource } from "../UIEventSource" | 
					
						
							|  |  |  | import { GlobalFilter } from "../../Models/GlobalFilter" | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  | import FilteredLayer from "../../Models/FilteredLayer" | 
					
						
							| 
									
										
										
										
											2023-03-25 02:48:24 +01:00
										 |  |  | import LayerConfig from "../../Models/ThemeConfig/LayerConfig" | 
					
						
							|  |  |  | import { OsmConnection } from "../Osm/OsmConnection" | 
					
						
							| 
									
										
										
										
											2023-04-26 18:04:42 +02:00
										 |  |  | import { Tag } from "../Tags/Tag" | 
					
						
							|  |  |  | import Translations from "../../UI/i18n/Translations" | 
					
						
							| 
									
										
										
										
											2023-05-01 01:12:39 +02:00
										 |  |  | import { RegexTag } from "../Tags/RegexTag" | 
					
						
							|  |  |  | import { Or } from "../Tags/Or" | 
					
						
							| 
									
										
										
										
											2023-03-25 02:48:24 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * The layer state keeps track of: | 
					
						
							|  |  |  |  * - Which layers are enabled | 
					
						
							|  |  |  |  * - Which filters are used, including 'global' filters | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | export default class LayerState { | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Filters which apply onto all layers | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public readonly globalFilters: UIEventSource<GlobalFilter[]> = new UIEventSource( | 
					
						
							|  |  |  |         [], | 
					
						
							|  |  |  |         "globalFilters" | 
					
						
							|  |  |  |     ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Which layers are enabled in the current theme and what filters are applied onto them | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |     public readonly filteredLayers: ReadonlyMap<string, FilteredLayer> | 
					
						
							| 
									
										
										
										
											2023-03-25 02:48:24 +01:00
										 |  |  |     private readonly osmConnection: OsmConnection | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param osmConnection | 
					
						
							|  |  |  |      * @param layers | 
					
						
							|  |  |  |      * @param context: the context, probably the name of the theme. Used to disambiguate the upstream user preference | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     constructor(osmConnection: OsmConnection, layers: LayerConfig[], context: string) { | 
					
						
							|  |  |  |         this.osmConnection = osmConnection | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |         const filteredLayers = new Map() | 
					
						
							| 
									
										
										
										
											2023-03-25 02:48:24 +01:00
										 |  |  |         for (const layer of layers) { | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |             filteredLayers.set( | 
					
						
							| 
									
										
										
										
											2023-03-28 05:13:48 +02:00
										 |  |  |                 layer.id, | 
					
						
							|  |  |  |                 FilteredLayer.initLinkedState(layer, context, this.osmConnection) | 
					
						
							| 
									
										
										
										
											2023-03-25 02:48:24 +01:00
										 |  |  |             ) | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |         this.filteredLayers = filteredLayers | 
					
						
							|  |  |  |         layers.forEach((l) => LayerState.linkFilterStates(l, filteredLayers)) | 
					
						
							| 
									
										
										
										
											2023-04-26 18:04:42 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Sets the global filter which looks to the 'level'-tag. | 
					
						
							|  |  |  |      * Only features with the given 'level' will be shown. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * If undefined is passed, _all_ levels will be shown | 
					
						
							|  |  |  |      * @param level | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public setLevelFilter(level?: string) { | 
					
						
							|  |  |  |         // Remove all previous
 | 
					
						
							|  |  |  |         const l = this.globalFilters.data.length | 
					
						
							|  |  |  |         this.globalFilters.data = this.globalFilters.data.filter((f) => f.id !== "level") | 
					
						
							|  |  |  |         if (!level) { | 
					
						
							|  |  |  |             if (l !== this.globalFilters.data.length) { | 
					
						
							|  |  |  |                 this.globalFilters.ping() | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         const t = Translations.t.general.levelSelection | 
					
						
							| 
									
										
										
										
											2023-05-25 10:45:17 +02:00
										 |  |  |         const conditionsOrred = [ | 
					
						
							|  |  |  |             new Tag("level", "" + level), | 
					
						
							|  |  |  |             new RegexTag("level", new RegExp("(.*;)?" + level + "(;.*)?")), | 
					
						
							|  |  |  |         ] | 
					
						
							|  |  |  |         if(level === "0") { | 
					
						
							|  |  |  |             conditionsOrred.push(new Tag("level", "")) // No level tag is the same as level '0'
 | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         console.log("Setting levels filter to", conditionsOrred) | 
					
						
							| 
									
										
										
										
											2023-04-26 18:04:42 +02:00
										 |  |  |         this.globalFilters.data.push({ | 
					
						
							|  |  |  |             id: "level", | 
					
						
							|  |  |  |             state: level, | 
					
						
							| 
									
										
										
										
											2023-05-25 10:45:17 +02:00
										 |  |  |             osmTags: new Or(conditionsOrred), | 
					
						
							| 
									
										
										
										
											2023-04-26 18:04:42 +02:00
										 |  |  |             onNewPoint: { | 
					
						
							|  |  |  |                 tags: [new Tag("level", level)], | 
					
						
							|  |  |  |                 icon: "./assets/svg/elevator.svg", | 
					
						
							|  |  |  |                 confirmAddNew: t.confirmLevel.PartialSubs({ level }), | 
					
						
							|  |  |  |                 safetyCheck: t.addNewOnLevel.Subs({ level }), | 
					
						
							|  |  |  |             }, | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |         this.globalFilters.ping() | 
					
						
							| 
									
										
										
										
											2023-03-25 02:48:24 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Some layers copy the filter state of another layer - this is quite often the case for 'sibling'-layers, | 
					
						
							|  |  |  |      * (where two variations of the same layer are used, e.g. a specific type of shop on all zoom levels and all shops on high zoom). | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * This methods links those states for the given layer | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |     private static linkFilterStates( | 
					
						
							|  |  |  |         layer: LayerConfig, | 
					
						
							|  |  |  |         filteredLayers: Map<string, FilteredLayer> | 
					
						
							|  |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2023-03-25 02:48:24 +01:00
										 |  |  |         if (layer.filterIsSameAs === undefined) { | 
					
						
							|  |  |  |             return | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2023-04-06 01:33:08 +02:00
										 |  |  |         const toReuse = filteredLayers.get(layer.filterIsSameAs) | 
					
						
							| 
									
										
										
										
											2023-03-25 02:48:24 +01:00
										 |  |  |         if (toReuse === undefined) { | 
					
						
							|  |  |  |             throw ( | 
					
						
							|  |  |  |                 "Error in layer " + | 
					
						
							|  |  |  |                 layer.id + | 
					
						
							|  |  |  |                 ": it defines that it should be use the filters of " + | 
					
						
							|  |  |  |                 layer.filterIsSameAs + | 
					
						
							|  |  |  |                 ", but this layer was not loaded" | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         console.warn( | 
					
						
							|  |  |  |             "Linking filter and isDisplayed-states of " + layer.id + " and " + layer.filterIsSameAs | 
					
						
							|  |  |  |         ) | 
					
						
							| 
									
										
										
										
											2023-04-14 17:53:08 +02:00
										 |  |  |         const copy = new FilteredLayer(layer, toReuse.appliedFilters, toReuse.isDisplayed) | 
					
						
							|  |  |  |         filteredLayers.set(layer.id, copy) | 
					
						
							| 
									
										
										
										
											2023-03-25 02:48:24 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | } |