Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@
"haloColor": "rgba(255, 255, 255, 0.7)",
"haloWidth": 2,
"declutterMode": "obstacle",
"minZoomLevel": 7
"minZoomLevel": 6
}
}
]
Expand All @@ -121,7 +121,7 @@
"haloColor": "#ffffff",
"haloWidth": 2,
"declutterMode": "declutter",
"minZoomLevel": 10
"minZoomLevel": 5
}
}
]
Expand Down
4 changes: 3 additions & 1 deletion packages/geoview-core/public/locales/en/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@
"legendInstructions": "Legend Instructions",
"noLayersAdded": "No layers added to the map",
"noLayersAddedDescription": "Add layers to the map by clicking on the 'Layers' button and adding the layers you want to display.",
"selectLayerAndScroll": "Show in Layers panel"
"selectLayerAndScroll": "Show in Layers panel",
"hideText": "Hide feature text labels",
"showText": "Show feature text labels"
},
"layers": {
"title": "Layers",
Expand Down
6 changes: 4 additions & 2 deletions packages/geoview-core/public/locales/fr/translation.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,12 @@
"highlightLayer": "Couche mise en évidence",
"subLayersCount": "{count} sous-couches",
"itemsCount": "{count} sur {totalCount} classes",
"legendInstructions": "Legend Instructions",
"legendInstructions": "Instructions de la légende",
"noLayersAdded": "Aucune couche ajoutée",
"noLayersAddedDescription": "Ajoutez des couches à la carte en cliquant sur le bouton 'Couches' et en sélectionnant les couches que vous souhaitez afficher.",
"selectLayerAndScroll": "Voir dans le panneau Couches"
"selectLayerAndScroll": "Voir dans le panneau Couches",
"hideText": "Masquer les étiquettes de texte des éléments",
"showText": "Afficher les étiquettes de texte des éléments"
},
"layers": {
"title": "Couches",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import type {
import { AbstractEventProcessor } from '@/api/event-processors/abstract-event-processor';
import { MapEventProcessor } from '@/api/event-processors/event-processor-children/map-event-processor';
import { AbstractGVLayer } from '@/geo/layer/gv-layers/abstract-gv-layer';
import { AbstractGVVector } from '@/geo/layer/gv-layers/vector/abstract-gv-vector';
import type { AbstractBaseLayerEntryConfig } from '@/api/config/validation-classes/abstract-base-layer-entry-config';
import { AbstractGVRaster } from '@/geo/layer/gv-layers/raster/abstract-gv-raster';
import { Projection } from '@/geo/utils/projection';
Expand Down Expand Up @@ -958,6 +959,8 @@ export class LegendEventProcessor extends AbstractEventProcessor {
// TODO: Encapsulate rasterFunction and possibly other 'settings' into their own object
rasterFunction: layer instanceof GVEsriImage ? layer.getRasterFunction() : undefined,
mosaicRule: layer instanceof GVEsriImage ? layer.getMosaicRule() : undefined,
hasText: layer instanceof AbstractGVVector ? layer.getTextOLLayer() !== undefined : undefined,
textVisible: layer instanceof AbstractGVVector ? layer.getTextVisible() : undefined,
};

// If layer is regular (not group)
Expand Down Expand Up @@ -1479,6 +1482,82 @@ export class LegendEventProcessor extends AbstractEventProcessor {
}
}

/**
* Checks if a layer has a text layer.
*
* @param mapId - The ID of the map.
* @param layerPath - The layer path of the layer to check.
* @returns True if the layer has a text layer, false otherwise.
*/
static getLayerHasText(mapId: string, layerPath: string): boolean {
const layer = MapEventProcessor.getMapViewerLayerAPI(mapId).getGeoviewLayerRegularIfExists(layerPath);

// Check if it's a vector layer with a text layer
if (layer && layer instanceof AbstractGVVector) {
return layer.getTextOLLayer() !== undefined;
}

return false;
}

/**
* Gets the text visibility state for a layer.
*
* @param mapId - The ID of the map.
* @param layerPath - The layer path of the layer to check.
* @returns True if text is visible, false otherwise. Returns undefined if layer has no text.
*/
static getLayerTextVisibility(mapId: string, layerPath: string): boolean | undefined {
const layer = MapEventProcessor.getMapViewerLayerAPI(mapId).getGeoviewLayerRegularIfExists(layerPath);

// Check if it's a vector layer with a text layer
if (layer && layer instanceof AbstractGVVector && layer.getTextOLLayer()) {
return layer.getTextVisible();
}

return undefined;
}

/**
* Sets the text visibility for a layer.
*
* @param mapId - The ID of the map.
* @param layerPath - The layer path of the layer to change.
* @param visible - True to show text, false to hide text.
*/
static setLayerTextVisibility(mapId: string, layerPath: string, visible: boolean): void {
// Get the layer
const layer = MapEventProcessor.getMapViewerLayerAPI(mapId).getGeoviewLayerRegular(layerPath);
if (!layer) return;

// If it's a vector layer, set text visibility
if (layer instanceof AbstractGVVector) {
layer.setTextVisible(visible);

this.setLayerTextVisibilityInStore(mapId, layerPath, visible);
}
}

/**
* Updates the text visibility state in the store.
*
* @param mapId - The ID of the map.
* @param layerPath - The layer path.
* @param textVisible - The new text visibility state.
*/
static setLayerTextVisibilityInStore(mapId: string, layerPath: string, textVisible: boolean): void {
// Find the layer for the given layer path
const layers = LegendEventProcessor.getLayerState(mapId).legendLayers;
const layer = this.findLayerByPath(layers, layerPath);

if (layer) {
// Set text visibility
layer.textVisible = textVisible;
// Set updated legend layers
this.getLayerState(mapId).setterActions.setLegendLayers(layers);
}
}

/**
* Sets the opacity of the layer and its children in the store.
* @param {string} mapId - The ID of the map.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import type { TypeHoverFeatureInfo } from '@/core/stores/store-interface-and-int
import { ConfigBaseClass } from '@/api/config/validation-classes/config-base-class';

import { InvalidExtentError, NoBoundsError, PluginError } from '@/core/exceptions/geoview-exceptions';
import { AbstractGVVector } from '@/geo/layer/gv-layers/vector/abstract-gv-vector';
import { AbstractGVVectorTile } from '@/geo/layer/gv-layers/vector/abstract-gv-vector-tile';
import { AbstractBaseLayerEntryConfig } from '@/api/config/validation-classes/abstract-base-layer-entry-config';
import { GroupLayerEntryConfig } from '@/api/config/validation-classes/group-layer-entry-config';
Expand Down Expand Up @@ -1432,7 +1433,16 @@ export class MapEventProcessor extends AbstractEventProcessor {
const reversedLayers = [...this.getMapStateProtected(mapId).orderedLayerInfo].reverse();
reversedLayers.forEach((orderedLayerInfo, index) => {
const olLayer = this.getMapViewerLayerAPI(mapId).getOLLayerIfExists(orderedLayerInfo.layerPath);
if (olLayer) olLayer?.setZIndex(index + 10);
if (olLayer) {
olLayer?.setZIndex(index + 10);

// Make sure text layer z-index above other vector layers
const gvLayer = this.getMapViewerLayerAPI(mapId).getGeoviewLayerIfExists(orderedLayerInfo.layerPath);
if (gvLayer instanceof AbstractGVVector) {
const textLayer = gvLayer.getTextOLLayer();
if (textLayer) textLayer.setZIndex(index + 110);
}
}
});
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import {
TimeSliderIcon,
Typography,
ZoomInSearchIcon,
TitleIcon,
FormatClearIcon,
} from '@/ui';
import { ListItemText } from '@/ui/list';
import {
Expand All @@ -35,6 +37,8 @@ import {
useLayerSelectorFilterClass,
useLayerStoreActions,
useLayerTimeDimension,
useLayerSelectorHasText,
useLayerSelectorTextVisibility,
} from '@/core/stores/store-interface-and-intial-values/layer-state';
import { useUIStoreActions, useUIActiveTrapGeoView } from '@/core/stores/store-interface-and-intial-values/ui-state';
import {
Expand Down Expand Up @@ -158,6 +162,7 @@ export function LayerDetails(props: LayerDetailsProps): JSX.Element {
getLayerSettings,
setLayerHoverable,
setLayerQueryable,
setLayerTextVisibility,
} = useLayerStoreActions();
const { setOrToggleLayerVisibility } = useMapStoreActions();
const { enableFocusTrap } = useUIStoreActions();
Expand Down Expand Up @@ -187,6 +192,8 @@ export function LayerDetails(props: LayerDetailsProps): JSX.Element {
const timeSliderLayers = useTimeSliderLayers();
const timeSliderActions = useTimeSliderStoreActions();
const isFocusTrap = useUIActiveTrapGeoView();
const hasText = useLayerSelectorHasText(layerDetails.layerPath);
const textVisible = useLayerSelectorTextVisibility(layerDetails.layerPath);

// Use navigate hook for time slider (only if time slider state exists)
const navigateToTimeSlider = useNavigateToTab(
Expand Down Expand Up @@ -469,6 +476,22 @@ export function LayerDetails(props: LayerDetailsProps): JSX.Element {
return null;
}

function renderToggleTextButton(): JSX.Element | null {
if (hasText) {
return (
<IconButton
aria-label={textVisible ? t('legend.hideText') : t('legend.showText')}
onClick={() => setLayerTextVisibility(layerDetails.layerPath, !textVisible)}
className="buttonOutline"
disabled={layerHidden}
>
{textVisible ? <TitleIcon /> : <FormatClearIcon />}
</IconButton>
);
}
return null;
}

function renderZoomButton(): JSX.Element | null {
if (isLayerZoomToExtentCapable)
return (
Expand Down Expand Up @@ -523,6 +546,7 @@ export function LayerDetails(props: LayerDetailsProps): JSX.Element {
<RestartAltIcon />
</IconButton>
{renderHighlightButton()}
{renderToggleTextButton()}
{renderZoomButton()}
{layerSettingsButton}
{deleteButton && <Box sx={sxClasses.verticalDivider} />}
Expand Down
3 changes: 3 additions & 0 deletions packages/geoview-core/src/core/components/layers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ export interface TypeLegendLayer {
hoverable?: boolean;
queryable?: boolean;

hasText?: boolean;
textVisible?: boolean;

icons: TypeLegendLayerItem[];
// data: TypeLegend | undefined | null;
items: TypeLegendItem[];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,13 @@ export interface ILayerState {
getLayerWmsStyle: (layerPath: string) => string | undefined;
getLayerWmsAvailableStyles: (layerPath: string) => TypeMetadataWMSCapabilityLayerStyle[] | undefined;
getLayerSettings: (layerPath: string) => string[];
getLayerHasText: (layerPath: string) => boolean;
getLayerTextVisibility: (layerPath: string) => boolean;
refreshLayer: (layerPath: string) => Promise<void>;
reloadLayer: (layerPath: string) => void;
toggleItemVisibility: (layerPath: string, item: TypeLegendItem) => void;
toggleItemVisibilityAndWait: (layerPath: string, item: TypeLegendItem) => Promise<void>;
setLayerTextVisibility: (layerPath: string, visible: boolean) => void;
setAllItemsVisibility: (layerPath: string, visibility: boolean) => void;
setAllItemsVisibilityAndWait: (layerPath: string, visibility: boolean) => Promise<void>;
setDisplayState: (newDisplayState: TypeLayersViewDisplayState) => void;
Expand Down Expand Up @@ -267,6 +270,26 @@ export function initializeLayerState(set: TypeSetStore, get: TypeGetStore): ILay
return LegendEventProcessor.getLayerSettings(get().mapId, layerPath);
},

/**
* Checks if a layer has a text layer.
* @param {string} layerPath - The layer path of the layer to check.
* @returns {boolean} True if the layer has a text layer, false otherwise.
*/
getLayerHasText: (layerPath: string): boolean => {
// Redirect to event processor
return LegendEventProcessor.getLayerHasText(get().mapId, layerPath);
},

/**
* Gets the text visibility state for a layer.
* @param {string} layerPath - The layer path of the layer to check.
* @returns {boolean | undefined} True if text is visible, false otherwise. Returns undefined if layer has no text.
*/
getLayerTextVisibility: (layerPath: string): boolean | undefined => {
// Redirect to event processor
return LegendEventProcessor.getLayerTextVisibility(get().mapId, layerPath);
},

/**
* Refresh layer and set states to original values.
* @param {string} layerPath - The layer path of the layer to change.
Expand Down Expand Up @@ -315,6 +338,16 @@ export function initializeLayerState(set: TypeSetStore, get: TypeGetStore): ILay
return LegendEventProcessor.toggleItemVisibility(get().mapId, layerPath, item, true);
},

/**
* Sets the text visibility for a layer.
* @param {string} layerPath - The layer path of the layer to change.
* @param {boolean} visible - True to show text, false to hide text.
*/
setLayerTextVisibility: (layerPath: string, visible: boolean): void => {
// Redirect to event processor
LegendEventProcessor.setLayerTextVisibility(get().mapId, layerPath, visible);
},

/**
* Sets the visibility of all legend items in a layer.
* This method updates the visibility of every item in the specified layer
Expand Down Expand Up @@ -904,6 +937,8 @@ export const useLayerSelectorStyleConfig = createLayerSelectorHook('styleConfig'
export const useLayerSelectorRasterFunction = createLayerSelectorHook('rasterFunction');
export const useLayerSelectorMosaicRule = createLayerSelectorHook('mosaicRule');
export const useLayerSelectorWmsStyle = createLayerSelectorHook('wmsStyle');
export const useLayerSelectorHasText = createLayerSelectorHook('hasText');
export const useLayerSelectorTextVisibility = createLayerSelectorHook('textVisible');

// Store Actions
export const useLayerStoreActions = (): LayerActions => useStore(useGeoViewStore(), (state) => state.layerState.actions);
Loading
Loading