import { Control } from 'ol/control';
import { Events } from '../definitions';
/**
* Creates a control for managing server side annotation layers
* @param {object} opt_options Options to initialize
* @param {string} [opt_options.className] The css class to apply to this control
* @param {string} [opt_options.tipLabel] Label for the button
* @param {boolean} [opt_options.collapsed] Whether the control starts collapsed
* @param {string} [opt_options.collapseLabel] The label to show when collapsed
* @param {Object} [opt_options.stateManager] The state manager to keep settings in sync
*/
export class LayerSwitch extends Control {
constructor(opt_options) {
var options = opt_options || {};
var element = document.createElement('div');
super({
element: element,
target: options.target
});
this.pmaViewport = options.pmaViewport;
this.stateManager = options.stateManager ? options.stateManager : null;
if (this.stateManager) {
if (!this.stateManager.layerSwitch) {
this.stateManager.layerSwitch = {};
this.stateManager.layerSwitch.collapsed = (options.collapsed) ? options.collapsed : false;
}
this.collapsed_ = this.stateManager.layerSwitch.collapsed === true;
}
else {
this.collapsed_ = (options.collapsed) ? options.collapsed : false;
}
var className = (options.className) ? options.className : 'ol-layerswitch';
var tipLabel = (options.tipLabel) ? options.tipLabel : 'Channels';
var collapseLabel = (options.collapseLabel) ? options.collapseLabel : '\u00BB';
this.collapseLabel_ = document.createElement('span');
this.collapseLabel_.innerHTML = collapseLabel;
var label = (options.label) ? options.label : '\u00AB';
this.label_ = document.createElement('span');
this.label_.innerHTML = label;
var activeLabel = this.collapsed_ ? this.collapseLabel_ : this.label_;
var button = document.createElement('button');
button.type = 'button';
button.title = tipLabel;
button.appendChild(activeLabel);
button.className = "collapse-button";
this.btnEventUsed = 'click';
if ('ontouchstart' in document.documentElement) {
this.btnEventUsed = 'touchstart';
}
button.addEventListener(this.btnEventUsed, this.buttonClk.bind(this), false);
var cssClasses = className + ' ' + 'ol-unselectable ol-control ' + (this.collapsed_ ? ' ol-collapsed' : '');
element.className = cssClasses;
element.appendChild(button);
this.panel_ = document.createElement('ul');
this.panel_.className = 'panel';
element.appendChild(this.panel_);
};
/**
* Sets the OpenLayers map this control handles. This is automatically called by OpenLayers
* @param {ol.Map} map
*/
setMap(map) {
super.setMap(map);
this.drawPanel();
};
/**
* Changes the visibility of the specified layers
* @param {Object[]} options - An array of options
* @param {string} options.name - The name of the layer to change the visibility
* @param {boolean} options.visible - Whether to show or hide the specified layer
* @param {number} [options.opacity] - A number between 0 and 1 that sets the opacity of the layer
*/
setLayersVisibility(options) {
if (!options || options.length == 0) {
return;
}
if (!this.getMap()) {
return;
}
var layers = this.getMap().getLayers().getArray();
for (var oi = 0; oi < options.length; oi++) {
var o = options[oi];
if (!o.name) {
continue;
}
for (var j = layers.length - 1; j >= 0; j--) {
// only check for groups
if (layers[j].getLayers) {
var groupLayers = layers[j].getLayers().getArray();
for (var i = groupLayers.length - 1; i >= 0; i--) {
var layer = groupLayers[i];
let lName = layer.get("title") || layer.get("name");
if (lName == o.name) {
layer.setVisible(o.visible);
if (!(o.opacity == null)) {
layer.setOpacity(o.opacity);
}
}
let li = this.panel_.querySelector(`li[data-name='${lName}']`);
if (li) {
let checkbox = li.querySelector("input[type=checkbox]");
checkbox.checked = layer.getVisible();
let range = li.querySelector("input[type=range]");
range.value = layer.getOpacity() * 100;
}
}
}
}
}
};
/**
* Gets the visibility of the specified layers
* @returns {Object[]} options - An array of options
* @returns {string} options.name - The name of the layer to change the visibility
* @returns {boolean} options.visible - Whether to show or hide the specified layer
*/
getLayersVisibility() {
if (!this.getMap()) {
return;
}
let result = [];
let layers = this.getMap().getLayers().getArray();
for (let j = layers.length - 1; j >= 0; j--) {
if (layers[j].getLayers) {
let groupLayers = layers[j].getLayers().getArray();
for (let i = groupLayers.length - 1; i >= 0; i--) {
let layer = groupLayers[i];
let lName = layer.get("title") || layer.get("name");
result.push({ name: lName, visible: layer.getVisible(), opacity: layer.getOpacity() });
}
}
}
return result;
}
// Draw the panel control (prevent multiple draw due to layers manipulation on the map with a delay function)
drawPanel(e) {
if (!this.getMap()) return;
var layers = this.getMap().getLayers().getArray();
this.panel_.innerHTML = '';
for (var j = layers.length - 1; j >= 0; j--) {
// only check for groups
if (layers[j].getLayers) {
var groupLayers = layers[j].getLayers().getArray();
for (var i = groupLayers.length - 1; i >= 0; i--) {
var layer = groupLayers[i];
// var showLayer = layer.get("displayInLayerSwitcher") !== false;
// if (!showLayer) {
// continue;
// }
var li = document.createElement('li');
li.setAttribute('data-name', layer.get("title") || layer.get("name"));
li.className = layer.getVisible() ? "visible " : " ";
this.panel_.appendChild(li);
var liHtml = "<input type='checkbox' " + (layer.getVisible() ? "checked='checked' " : "") + "/>";
liHtml += "<label title='" + (layer.get("title") || layer.get("name")) + "'>" + (layer.get("title") || layer.get("name")) + "</label>";
liHtml += "<input type=\"range\" min=\"0\" max=\"100\" value=\"" + layer.getOpacity() * 100 + "\" name=\"layer-opacity\" >";
li.innerHTML = liHtml;
let checkbox = li.querySelector("input[type=checkbox]");
checkbox.addEventListener('change', switchVisibility.bind(this, layer, checkbox), false);
let label = li.querySelector("label");
label.addEventListener(this.btnEventUsed, switchVisibility.bind(this, layer, checkbox), false);
let range = li.querySelector("input[type=range]");
range.addEventListener('change', opacityChange.bind(this, layer, range), false);
}
}
}
function switchVisibility(layer, checkbox) {
layer.setVisible(!layer.getVisible());
checkbox.checked = layer.getVisible();
if (this.pmaViewport) {
this.pmaViewport.fireEvent(Events.AnnotationLayerChanged, this.pmaViewport);
}
}
function opacityChange(layer, range) {
layer.setOpacity(range.value / 100);
if (this.pmaViewport) {
this.pmaViewport.fireEvent(Events.AnnotationLayerChanged, this.pmaViewport);
}
}
};
/**
* Gets the collapsed state of the control
* @return {boolean} True if the control is currently collapsed
*/
getCollapsed() {
return (" " + this.element.className + " ").indexOf(' ol-collapsed ') > -1;
};
/**
* Sets the collapsed state of the control
* @param {boolean} collapsed - True to collapse the control, otherwise false
*/
setCollapsed(collapsed) {
if (this.getCollapsed() != collapsed) {
this.buttonClk();
}
};
buttonClk(event) {
if (event) {
event.preventDefault();
event.stopPropagation();
}
if ((" " + this.element.className + " ").indexOf(' ol-collapsed ') > -1) {
this.element.className = this.element.className.replace(/ol-collapsed/g, '');
}
else {
this.element.className += ' ol-collapsed';
}
if (!this.collapsed_) {
this.label_.parentNode.replaceChild(this.collapseLabel_, this.label_);
} else {
this.collapseLabel_.parentNode.replaceChild(this.label_, this.collapseLabel_);
}
this.collapsed_ = !this.collapsed_;
if (this.stateManager) {
this.stateManager.layerSwitch.collapsed = this.collapsed_;
}
}
}