/* Copyright (c) 2015-present The Open Source Geospatial Foundation
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* The layer tree node class used by the stores used in trees.
*
* @class GeoExt.data.model.LayerTreeNode
*/
Ext.define(
'GeoExt.data.model.LayerTreeNode',
{
extend: 'GeoExt.data.model.Layer',
requires: ['Ext.data.NodeInterface'],
mixins: ['Ext.mixin.Queryable', 'GeoExt.mixin.SymbolCheck'],
// <debug>
symbols: ['ol.layer.Base', 'ol.Object#get', 'ol.Object#set'],
// </debug>
fields: [
{
name: 'leaf',
type: 'boolean',
convert: function (v, record) {
const isGroup = record.get('isLayerGroup');
if (isGroup === undefined || isGroup) {
return false;
}
return true;
},
},
{
/**
* This should be set via tree panel.
*/
name: '__toggleMode',
type: 'string',
defaultValue: 'classic',
},
{
name: 'iconCls',
type: 'string',
convert: function (v, record) {
return record.getOlLayerProp('iconCls');
},
},
],
proxy: {
type: 'memory',
reader: {
type: 'json',
},
},
/**
* @inheritDoc
*/
constructor: function () {
this.callParent(arguments);
const layer = this.getOlLayer();
if (layer instanceof ol.layer.Base) {
this.set('checked', layer.get('visible'));
layer.on('change:visible', this.onLayerVisibleChange.bind(this));
}
},
/**
* Handler for the `change:visible` event of the layer.
*
* @param {ol.ObjectEvent} evt The emitted `ol.Object` event.
*/
onLayerVisibleChange: function (evt) {
const target = evt.target;
if (!this.__updating) {
this.set('checked', target.get('visible'));
}
},
/**
* Overridden to forward changes to the underlying `ol.Object`. All changes
* on the {Ext.data.Model} properties will be set on the `ol.Object` as
* well.
*
* @param {string} key The key to set.
* @param {Object} newValue The value to set.
*
* @inheritdoc
*/
set: function (key, newValue) {
const me = this;
const classicMode = me.get('__toggleMode') === 'classic';
me.callParent(arguments);
// forward changes to ol object
if (key === 'checked') {
if (me.get('__toggleMode') === 'ol3') {
me.getOlLayer().set('visible', newValue);
return;
}
me.__updating = true;
if (me.get('isLayerGroup') && classicMode) {
me.getOlLayer().set('visible', newValue);
if (me.childNodes) {
me.eachChild(function (child) {
child.getOlLayer().set('visible', newValue);
});
}
} else {
me.getOlLayer().set('visible', newValue);
}
me.__updating = false;
if (classicMode) {
me.toggleParentNodes(newValue);
}
}
},
/**
* Handles parent behaviour of checked nodes: Checks parent Nodes if node
* is checked or unchecks parent nodes if the node is unchecked and no
* sibling is checked.
*
* @param {boolean} newValue The newValue to pass through to the parent.
* @private
*/
toggleParentNodes: function (newValue) {
const me = this;
// Checks parent Nodes if node is checked.
if (newValue === true) {
me.__updating = true;
me.bubble(function (parent) {
if (!parent.isRoot()) {
parent.set('__toggleMode', 'ol3'); // prevents recursion
parent.set('checked', true);
parent.set('__toggleMode', 'classic');
}
});
me.__updating = false;
}
// Unchecks parent Nodes if the node is unchecked and no sibling is
// checked.
if (newValue === false) {
me.__updating = true;
me.bubble(function (parent) {
if (!parent.isRoot()) {
let allUnchecked = true;
parent.eachChild(function (child) {
if (child.get('checked')) {
allUnchecked = false;
}
});
if (allUnchecked) {
parent.set('__toggleMode', 'ol3'); // prevents recursion
parent.set('checked', false);
parent.set('__toggleMode', 'classic');
}
}
});
me.__updating = false;
}
},
/**
* @inheritdoc
*/
getRefItems: function () {
return this.childNodes;
},
/**
* @inheritdoc
*/
getRefOwner: function () {
return this.parentNode;
},
},
function () {
// make this an Ext.data.TreeModel
Ext.data.NodeInterface.decorate(this);
},
);