diff --git a/contribs/gmf/src/editing/Snapping.js b/contribs/gmf/src/editing/Snapping.js index edfc1473028..d234b43a861 100644 --- a/contribs/gmf/src/editing/Snapping.js +++ b/contribs/gmf/src/editing/Snapping.js @@ -264,7 +264,7 @@ EditingSnappingService.prototype.registerTreeCtrl_ = function(treeCtrl) { const uid = olUtilGetUid(treeCtrl); const stateWatcherUnregister = this.rootScope_.$watch( - () => treeCtrl.getState(), + () => this.isSnappingActiveForTreeCtrl_(treeCtrl), this.handleTreeCtrlStateChange_.bind(this, treeCtrl) ); @@ -287,7 +287,7 @@ EditingSnappingService.prototype.registerTreeCtrl_ = function(treeCtrl) { }; // This extra call is to initialize the treeCtrl with its current state - this.handleTreeCtrlStateChange_(treeCtrl, treeCtrl.getState()); + this.handleTreeCtrlStateChange_(treeCtrl, this.isSnappingActiveForTreeCtrl_(treeCtrl)); } } }; @@ -410,7 +410,30 @@ EditingSnappingService.prototype.getWFSConfig_ = function(treeCtrl) { /** * @param {import("ngeo/layertree/Controller.js").LayertreeController} treeCtrl The layer tree controller - * @param {string|undefined} newVal New state value + * @return {boolean} True if state is on and snapping is activated for that layer. + * @private + */ +EditingSnappingService.prototype.isSnappingActiveForTreeCtrl_ = function(treeCtrl) { + // Note: a snappable treeCtrl can only be a leaf, therefore the only possible + // states are: 'on' and 'off'. + if (treeCtrl.getState() !== 'on') { + return false; + } + if (treeCtrl.properties.snapping !== undefined) { + if (typeof treeCtrl.properties.snapping !== 'boolean') { + throw new Error('Wrong snappingActive type'); + } + return treeCtrl.properties.snapping; + } + const node = /** @type {import('gmf/themes.js').GmfLayer} */ (treeCtrl.node); + const config = getSnappingConfig(node); + return config !== null && config.activated; +}; + + +/** + * @param {import("ngeo/layertree/Controller.js").LayertreeController} treeCtrl The layer tree controller + * @param {boolean} newVal New value for the layer * @private */ EditingSnappingService.prototype.handleTreeCtrlStateChange_ = function(treeCtrl, newVal) { @@ -418,13 +441,7 @@ EditingSnappingService.prototype.handleTreeCtrlStateChange_ = function(treeCtrl, const uid = olUtilGetUid(treeCtrl); const item = this.cache_[uid]; - // Note: a snappable treeCtrl can only be a leaf, therefore the only possible - // states are: 'on' and 'off'. - if (newVal === 'on') { - this.activateItem_(item); - } else { - this.deactivateItem_(item); - } + newVal ? this.activateItem_(item) : this.deactivateItem_(item); }; diff --git a/contribs/gmf/src/layertree/component.html b/contribs/gmf/src/layertree/component.html index d41d8545919..99a267af1e0 100644 --- a/contribs/gmf/src/layertree/component.html +++ b/contribs/gmf/src/layertree/component.html @@ -118,6 +118,14 @@ title="{{'Currently editing this layer'|translate}}" ng-if="layertreeCtrl.properties.editing"> + + + diff --git a/contribs/gmf/src/layertree/component.js b/contribs/gmf/src/layertree/component.js index 6a66ff80f40..4bcdaa195ea 100644 --- a/contribs/gmf/src/layertree/component.js +++ b/contribs/gmf/src/layertree/component.js @@ -8,7 +8,8 @@ import gmfLayertreeDatasourceGroupTreeComponent from 'gmf/layertree/datasourceGr import gmfLayertreeSyncLayertreeMap from 'gmf/layertree/SyncLayertreeMap.js'; import gmfLayertreeTreeManager from 'gmf/layertree/TreeManager.js'; -import gmfThemeThemes, {getNodeMinResolution, getNodeMaxResolution} from 'gmf/theme/Themes.js'; +import gmfThemeThemes, +{getNodeMinResolution, getNodeMaxResolution, getSnappingConfig} from 'gmf/theme/Themes.js'; import ngeoDatasourceOGC, {ServerType} from 'ngeo/datasource/OGC.js'; import ngeoLayertreeComponent from 'ngeo/layertree/component.js'; @@ -156,6 +157,7 @@ function gmfLayertreeTemplate($element, $attrs, gmfLayertreeTemplate) { * * `printLayers`: A WMS layer that will be used instead of the WMTS layers in the print. * * `queryLayers`: The WMS layers used as references to query the WMTS layers. For WMTS layers. * * `isExpanded`: Whether the layer group is expanded by default. For layer groups (only). + * * `snappingConfig`: Whether the layer is used for snapping. * * @htmlAttribute {import("ol/Map.js").default} gmf-layertree-map The map. * @htmlAttribute {Object|undefined} gmf-layertree-dimensions Global dimensions object. @@ -463,6 +465,7 @@ Controller.prototype.listeners = function(scope, treeCtrl) { }); }; + /** * Toggle the state of treeCtrl's node. * @param {import("ngeo/layertree/Controller.js").LayertreeController} treeCtrl ngeo layertree controller, @@ -655,6 +658,34 @@ Controller.prototype.getScale_ = function() { }; +/** + * Is snapping activated for this LayertreeController + * @param {import("ngeo/layertree/Controller.js").LayertreeController} treeCtrl ngeo layertree controller. + * @return {boolean} True if snapping is activated for that layer. + */ +Controller.prototype.isSnappingActivated = function(treeCtrl) { + if (treeCtrl.properties.snapping !== undefined) { + if (typeof treeCtrl.properties.snapping !== 'boolean') { + throw new Error('Wrong snappingActive type'); + } + return treeCtrl.properties.snapping; + } + // Default to node.metadata.activated + const node = /** @type {import('gmf/themes.js').GmfLayer} */ (treeCtrl.node); + const config = getSnappingConfig(node); + return config != null && config.activated; +}; + + +/** + * Toggle snapping for this LayertreeController. + * @param {import("ngeo/layertree/Controller.js").LayertreeController} treeCtrl ngeo layertree controller. + */ +Controller.prototype.toggleSnapping = function(treeCtrl) { + treeCtrl.properties.snapping = !this.isSnappingActivated(treeCtrl); +}; + + /** * Opens a openIframePopup with the content of the metadata url of a node. * @param {import("ngeo/layertree/Controller.js").LayertreeController} treeCtrl ngeo layertree controller, diff --git a/contribs/gmf/src/theme/Themes.js b/contribs/gmf/src/theme/Themes.js index c5a059d4369..77fc20408fd 100644 --- a/contribs/gmf/src/theme/Themes.js +++ b/contribs/gmf/src/theme/Themes.js @@ -570,6 +570,10 @@ export function getFlatNodes(node, nodes) { export function getSnappingConfig(node) { const config = (node.metadata && node.metadata.snappingConfig !== undefined) ? node.metadata.snappingConfig : null; + // config.activated default to true + if (config && config.activated === undefined) { + config.activated = true; + } return config; } diff --git a/contribs/gmf/src/themes.js b/contribs/gmf/src/themes.js index 530dbc3d422..b8f9a242325 100644 --- a/contribs/gmf/src/themes.js +++ b/contribs/gmf/src/themes.js @@ -233,6 +233,7 @@ /** * @typedef {Object} GmfSnappingConfig + * @property {boolean} [activated=true] Determines whether the snapping on this layer is activated by default. * @property {boolean} [edge=true] Determines whethers the edges of features from the node layer can be * snapped or not. * @property {number} [tolerance=10] The tolerance in pixels the snapping should occur for the node layer.