forked from MapComplete/MapComplete
		
	Refactoring of AvailableBaseLayer
This commit is contained in:
		
							parent
							
								
									99512724e0
								
							
						
					
					
						commit
						7deb9b5d53
					
				
					 5 changed files with 90 additions and 79 deletions
				
			
		| 
						 | 
					@ -341,7 +341,7 @@ export class InitUiElements {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static InitBaseMap() {
 | 
					    private static InitBaseMap() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        State.state.availableBackgroundLayers = new AvailableBaseLayers(State.state.locationControl).availableEditorLayers;
 | 
					        State.state.availableBackgroundLayers = AvailableBaseLayers.AvailableLayersAt(State.state.locationControl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        State.state.backgroundLayer = State.state.backgroundLayerId
 | 
					        State.state.backgroundLayer = State.state.backgroundLayerId
 | 
				
			||||||
            .map((selectedId: string) => {
 | 
					            .map((selectedId: string) => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,7 +7,6 @@ import {UIEventSource} from "../UIEventSource";
 | 
				
			||||||
import {GeoOperations} from "../GeoOperations";
 | 
					import {GeoOperations} from "../GeoOperations";
 | 
				
			||||||
import {Utils} from "../../Utils";
 | 
					import {Utils} from "../../Utils";
 | 
				
			||||||
import Loc from "../../Models/Loc";
 | 
					import Loc from "../../Models/Loc";
 | 
				
			||||||
import {isBoolean} from "util";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Calculates which layers are available at the current location
 | 
					 * Calculates which layers are available at the current location
 | 
				
			||||||
| 
						 | 
					@ -31,22 +30,18 @@ export default class AvailableBaseLayers {
 | 
				
			||||||
            category: "osmbasedmap"
 | 
					            category: "osmbasedmap"
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
    public static layerOverview = AvailableBaseLayers.LoadRasterIndex().concat(AvailableBaseLayers.LoadProviderIndex());
 | 
					    public static layerOverview = AvailableBaseLayers.LoadRasterIndex().concat(AvailableBaseLayers.LoadProviderIndex());
 | 
				
			||||||
    public availableEditorLayers: UIEventSource<BaseLayer[]>;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(location: UIEventSource<Loc>) {
 | 
					    public static AvailableLayersAt(location: UIEventSource<Loc>): UIEventSource<BaseLayer[]> {
 | 
				
			||||||
        const self = this;
 | 
					        const source = location.map(
 | 
				
			||||||
        this.availableEditorLayers =
 | 
					 | 
				
			||||||
            location.map(
 | 
					 | 
				
			||||||
            (currentLocation) => {
 | 
					            (currentLocation) => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (currentLocation === undefined) {
 | 
					                if (currentLocation === undefined) {
 | 
				
			||||||
                    return AvailableBaseLayers.layerOverview;
 | 
					                    return AvailableBaseLayers.layerOverview;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    const currentLayers = self.availableEditorLayers?.data;
 | 
					                const currentLayers = source?.data; // A bit unorthodox - I know
 | 
				
			||||||
                    const newLayers = AvailableBaseLayers.AvailableLayersAt(currentLocation?.lon, currentLocation?.lat);
 | 
					                const newLayers = AvailableBaseLayers.CalculateAvailableLayersAt(currentLocation?.lon, currentLocation?.lat);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if (currentLayers === undefined) {
 | 
					                if (currentLayers === undefined) {
 | 
				
			||||||
                    return newLayers;
 | 
					                    return newLayers;
 | 
				
			||||||
| 
						 | 
					@ -62,11 +57,55 @@ export default class AvailableBaseLayers {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return currentLayers;
 | 
					                return currentLayers;
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
 | 
					        return source;
 | 
				
			||||||
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    private static AvailableLayersAt(lon: number, lat: number): BaseLayer[] {
 | 
					    public static SelectBestLayerAccordingTo(location: UIEventSource<Loc>, preferedCategory: UIEventSource<string | string[]>): UIEventSource<BaseLayer> {
 | 
				
			||||||
 | 
					        return AvailableBaseLayers.AvailableLayersAt(location).map(available => {
 | 
				
			||||||
 | 
					            // First float all 'best layers' to the top
 | 
				
			||||||
 | 
					            available.sort((a, b) => {
 | 
				
			||||||
 | 
					                    if (a.isBest && b.isBest) {
 | 
				
			||||||
 | 
					                        return 0;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    if (!a.isBest) {
 | 
				
			||||||
 | 
					                        return 1
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    return -1;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if (preferedCategory.data === undefined) {
 | 
				
			||||||
 | 
					                return available[0]
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let prefered: string []
 | 
				
			||||||
 | 
					            if (typeof preferedCategory.data === "string") {
 | 
				
			||||||
 | 
					                prefered = [preferedCategory.data]
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                prefered = preferedCategory.data;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            prefered.reverse();
 | 
				
			||||||
 | 
					            for (const category of prefered) {
 | 
				
			||||||
 | 
					                //Then sort all 'photo'-layers to the top. Stability of the sorting will force a 'best' photo layer on top
 | 
				
			||||||
 | 
					                available.sort((a, b) => {
 | 
				
			||||||
 | 
					                        if (a.category === category && b.category === category) {
 | 
				
			||||||
 | 
					                            return 0;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        if (a.category !== category) {
 | 
				
			||||||
 | 
					                            return 1
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        return -1;
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                )
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return available[0]
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private static CalculateAvailableLayersAt(lon: number, lat: number): BaseLayer[] {
 | 
				
			||||||
        const availableLayers = [AvailableBaseLayers.osmCarto]
 | 
					        const availableLayers = [AvailableBaseLayers.osmCarto]
 | 
				
			||||||
        const globalLayers = [];
 | 
					        const globalLayers = [];
 | 
				
			||||||
        for (const layerOverviewItem of AvailableBaseLayers.layerOverview) {
 | 
					        for (const layerOverviewItem of AvailableBaseLayers.layerOverview) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -19,6 +19,7 @@ import {Translation} from "../i18n/Translation";
 | 
				
			||||||
import LocationInput from "../Input/LocationInput";
 | 
					import LocationInput from "../Input/LocationInput";
 | 
				
			||||||
import {InputElement} from "../Input/InputElement";
 | 
					import {InputElement} from "../Input/InputElement";
 | 
				
			||||||
import Loc from "../../Models/Loc";
 | 
					import Loc from "../../Models/Loc";
 | 
				
			||||||
 | 
					import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
* The SimpleAddUI is a single panel, which can have multiple states:
 | 
					* The SimpleAddUI is a single panel, which can have multiple states:
 | 
				
			||||||
| 
						 | 
					@ -115,14 +116,21 @@ export default class SimpleAddUI extends Toggle {
 | 
				
			||||||
        let location = State.state.LastClickLocation;
 | 
					        let location = State.state.LastClickLocation;
 | 
				
			||||||
        let preciseInput: InputElement<Loc> = undefined
 | 
					        let preciseInput: InputElement<Loc> = undefined
 | 
				
			||||||
        if (preset.preciseInput !== undefined) {
 | 
					        if (preset.preciseInput !== undefined) {
 | 
				
			||||||
            preciseInput = new LocationInput({
 | 
					            const locationSrc = new UIEventSource({
 | 
				
			||||||
                preferCategory: preset.preciseInput.preferredBackground ?? State.state.backgroundLayer,
 | 
					 | 
				
			||||||
                centerLocation:
 | 
					 | 
				
			||||||
                    new UIEventSource({
 | 
					 | 
				
			||||||
                lat: location.data.lat,
 | 
					                lat: location.data.lat,
 | 
				
			||||||
                lon: location.data.lon,
 | 
					                lon: location.data.lon,
 | 
				
			||||||
                zoom: 19
 | 
					                zoom: 19
 | 
				
			||||||
                    })
 | 
					            });
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            let backgroundLayer = undefined;
 | 
				
			||||||
 | 
					            if(preset.preciseInput.preferredBackground){
 | 
				
			||||||
 | 
					               backgroundLayer= AvailableBaseLayers.SelectBestLayerAccordingTo(locationSrc, new UIEventSource<string | string[]>(preset.preciseInput.preferredBackground))
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            preciseInput = new LocationInput({
 | 
				
			||||||
 | 
					                mapBackground: backgroundLayer,
 | 
				
			||||||
 | 
					                centerLocation:locationSrc
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
            })
 | 
					            })
 | 
				
			||||||
            preciseInput.SetClass("h-32 rounded-xl overflow-hidden border border-gray").SetStyle("height: 12rem;")
 | 
					            preciseInput.SetClass("h-32 rounded-xl overflow-hidden border border-gray").SetStyle("height: 12rem;")
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,30 +2,27 @@ import {InputElement} from "./InputElement";
 | 
				
			||||||
import Loc from "../../Models/Loc";
 | 
					import Loc from "../../Models/Loc";
 | 
				
			||||||
import {UIEventSource} from "../../Logic/UIEventSource";
 | 
					import {UIEventSource} from "../../Logic/UIEventSource";
 | 
				
			||||||
import Minimap from "../Base/Minimap";
 | 
					import Minimap from "../Base/Minimap";
 | 
				
			||||||
import AvailableBaseLayers from "../../Logic/Actors/AvailableBaseLayers";
 | 
					 | 
				
			||||||
import BaseLayer from "../../Models/BaseLayer";
 | 
					import BaseLayer from "../../Models/BaseLayer";
 | 
				
			||||||
import Combine from "../Base/Combine";
 | 
					import Combine from "../Base/Combine";
 | 
				
			||||||
import Svg from "../../Svg";
 | 
					import Svg from "../../Svg";
 | 
				
			||||||
 | 
					import State from "../../State";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default class LocationInput extends InputElement<Loc> {
 | 
					export default class LocationInput extends InputElement<Loc> {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
 | 
					    IsSelected: UIEventSource<boolean> = new UIEventSource<boolean>(false);
 | 
				
			||||||
    private _centerLocation: UIEventSource<Loc>;
 | 
					    private _centerLocation: UIEventSource<Loc>;
 | 
				
			||||||
    private readonly preferCategory;
 | 
					    private readonly mapBackground : UIEventSource<BaseLayer>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor(options?: {
 | 
					    constructor(options?: {
 | 
				
			||||||
 | 
					        mapBackground?: UIEventSource<BaseLayer>,
 | 
				
			||||||
        centerLocation?: UIEventSource<Loc>,
 | 
					        centerLocation?: UIEventSource<Loc>,
 | 
				
			||||||
        preferCategory?: string | UIEventSource<string>,
 | 
					 | 
				
			||||||
    }) {
 | 
					    }) {
 | 
				
			||||||
        super();
 | 
					        super();
 | 
				
			||||||
        options = options ?? {}
 | 
					        options = options ?? {}
 | 
				
			||||||
        options.centerLocation = options.centerLocation ?? new UIEventSource<Loc>({lat: 0, lon: 0, zoom: 1})
 | 
					        options.centerLocation = options.centerLocation ?? new UIEventSource<Loc>({lat: 0, lon: 0, zoom: 1})
 | 
				
			||||||
        this._centerLocation = options.centerLocation;
 | 
					        this._centerLocation = options.centerLocation;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if(typeof options.preferCategory === "string"){
 | 
					        this.mapBackground = options.mapBackground ?? State.state.backgroundLayer
 | 
				
			||||||
            options.preferCategory = new UIEventSource<string>(options.preferCategory);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        this.preferCategory = options.preferCategory ?? new UIEventSource<string>(undefined)
 | 
					 | 
				
			||||||
        this.SetClass("block h-full")
 | 
					        this.SetClass("block h-full")
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,43 +35,10 @@ export default class LocationInput extends InputElement<Loc> {
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected InnerConstructElement(): HTMLElement {
 | 
					    protected InnerConstructElement(): HTMLElement {
 | 
				
			||||||
        const layer: UIEventSource<BaseLayer> = new AvailableBaseLayers(this._centerLocation).availableEditorLayers.map(allLayers => {
 | 
					 | 
				
			||||||
                // First float all 'best layers' to the top
 | 
					 | 
				
			||||||
                allLayers.sort((a, b) => {
 | 
					 | 
				
			||||||
                        if (a.isBest && b.isBest) {
 | 
					 | 
				
			||||||
                            return 0;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                        if (!a.isBest) {
 | 
					 | 
				
			||||||
                            return 1
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        return -1;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
                if (this.preferCategory) {
 | 
					 | 
				
			||||||
                    const self = this;
 | 
					 | 
				
			||||||
                    //Then sort all 'photo'-layers to the top. Stability of the sorting will force a 'best' photo layer on top
 | 
					 | 
				
			||||||
                    allLayers.sort((a, b) => {
 | 
					 | 
				
			||||||
                            const preferred = self.preferCategory.data
 | 
					 | 
				
			||||||
                            if (a.category === preferred && b.category === preferred) {
 | 
					 | 
				
			||||||
                                return 0;
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                            if (a.category !== preferred) {
 | 
					 | 
				
			||||||
                                return 1
 | 
					 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            return -1;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
                return allLayers[0]
 | 
					 | 
				
			||||||
            }, [this.preferCategory]
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        layer.addCallbackAndRunD(layer => console.log(layer))
 | 
					 | 
				
			||||||
        const map = new Minimap(
 | 
					        const map = new Minimap(
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                location: this._centerLocation,
 | 
					                location: this._centerLocation,
 | 
				
			||||||
                background: layer
 | 
					                background: this.mapBackground
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
        map.leafletMap.addCallbackAndRunD(leaflet => {
 | 
					        map.leafletMap.addCallbackAndRunD(leaflet => {
 | 
				
			||||||
| 
						 | 
					@ -84,7 +48,7 @@ export default class LocationInput extends InputElement<Loc> {
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        layer.map(layer => {
 | 
					        this.mapBackground.map(layer => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            const leaflet = map.leafletMap.data
 | 
					            const leaflet = map.leafletMap.data
 | 
				
			||||||
            if (leaflet === undefined || layer === undefined) {
 | 
					            if (leaflet === undefined || layer === undefined) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue