Ol-layerswitcher

Has anyone added GitHub - walkermatt/ol-layerswitcher: Layer control for OpenLayers to Jmix Map yet?

How do I do that?

Hi Benoît!

Could you clarify which features you need from the Layer Switcher? To integrate it with GeoMap, you’ll need to extend the GeoMap component and run some JavaScript code to update the added layers.

I’ve prepared a demo project that uses the Layer Switcher. In this project, I imported BaseObjectMap to detect added layers and set the correct labels. This import comes from generated/jar-resource/... , which may change in future Vaadin releases. Therefore, I wouldn’t recommend using it in production.

I think you can implement a similar popup using Jmix components. For example, you could create a button with popup content, like this:

View descriptor
<layout classNames="relative">
    <button id="jmixLayerSwitcherButton"
            icon="CHEVRON_CIRCLE_DOWN_O"
            themeNames="tertiary-inline"
            classNames="jmix-button-layer-switcher"/>
    <maps:geoMap id="map" height="100%" width="100%">
        <maps:layers>
            <maps:tile id="osmLayer">
                <maps:osmSource/>
            </maps:tile>
            <maps:vector id="vectorLayer">
                <maps:vectorSource/>
            </maps:vector>
        </maps:layers>
    </maps:geoMap>
</layout>
View controller
@ViewComponent
private GeoMap map;
@ViewComponent
private MessageBundle messageBundle;

@Subscribe
public void onInit(final InitEvent event) {
    createLayersPopover();
}

protected void createLayersPopover() {
    Popover popover = new Popover();
    popover.setFor("jmixLayerSwitcherButton");

    CheckboxGroup<Layer<?>> layersCheckboxGroup = new CheckboxGroup<>();
    layersCheckboxGroup.addThemeVariants(CheckboxGroupVariant.LUMO_VERTICAL);
    layersCheckboxGroup.setItems(new ListDataProvider<>(map.getLayers()));
    layersCheckboxGroup.setValue(new HashSet<>(map.getLayers()));
    layersCheckboxGroup.setItemLabelGenerator(layer -> messageBundle.getMessage("map.layer." + layer.getId()));
    layersCheckboxGroup.addValueChangeListener(event -> {
        map.getLayers().forEach(layer ->
                layer.setVisible(event.getValue().contains(layer)));
    });

    popover.add(layersCheckboxGroup);
    getContent().add(popover);
}

jmix-layer-switcher

Demo project: layer-switcher.zip (198.4 KB)

Thanks,

I adapted your code to inject the layers switch button from the controller, so I could use it in any screen with a map

fun createLayersPopover(map: GeoMap, origin: View<*>) {
        val view = origin.content as ViewLayout
        if (view.findComponent("jmixLayerSwitcherButton").getOrNull() == null) {
            val parentMap = map.parent.get()
            val button = uiComponents.create(JmixButton::class.java).apply {
                icon = Icon(VaadinIcon.CHEVRON_CIRCLE_DOWN_O)
                addClassNames("z-10", "absolute", "top-s", "end-s", "bg-base", "text-xl")
                addThemeVariants(ButtonVariant.LUMO_TERTIARY_INLINE)  // Use tertiary style for icon buttons
                setId("jmixLayerSwitcherButton")
            }
            val children = (parentMap as HasOrderedComponents).children
            parentMap.removeAll()
            children.forEach {
                if (it == map) {
                    val mapBox = uiComponents.create(HorizontalLayout::class.java).apply {
                        addClassNames("relative", "w-full", "h-full")
                    }
                    mapBox.add(it)
                    mapBox.add(button)
                    parentMap.add(mapBox)
                }
                else
                    parentMap.add(it)
            }
        }

        val popover = Popover()
        popover.setFor("jmixLayerSwitcherButton");

        val layersCheckboxGroup = CheckboxGroup<Layer<*>>()
        layersCheckboxGroup.addThemeVariants(CheckboxGroupVariant.LUMO_VERTICAL)
        layersCheckboxGroup.setItems(ListDataProvider(map.layers.sortedBy { it.zIndex }))
        layersCheckboxGroup.value = HashSet(map.layers.filter { it.visible != false })
        layersCheckboxGroup.setItemLabelGenerator { layer ->
            when (layer) {
                is TileLayer -> {
                    try {
                        //
                        dataManger.find from my app WMS table with  layer.id
                    } catch (e: IllegalArgumentException) {
                        null
                    }?.name
                        ?: messages.getMessage(origin.javaClass.name, "tile.layer.${layer.id}")
                }

                is VectorLayer -> {
                    messages.getMessage(origin.javaClass.name, "vector.layer.${layer.id}")
                }

                else -> messages.getMessage(origin.javaClass.name, "other.layer.${layer.id}")
            }
        }
        layersCheckboxGroup.addValueChangeListener { event ->
            map.layers.forEach { layer ->
                layer.visible = event.getValue().contains(layer)
            }
        }

        popover.add(layersCheckboxGroup);
        view.add(popover)
    }
1 Like