import { Control } from "ol/control";
import { Viewport } from "../viewport";
/**
* Displays an interface that allows the user to rotate the viewport
* @param {object} opt_options Options to initialize the rotation control
* @param {Viewport} opt_options.pmaViewport Viewport instance this control belongs to
* @param {string} [opt_options.resetTipLabel] Label for reset rotation button
* @param {string} [opt_options.flipHorizontallyTipLabel] Label for horizontal flip button
* @param {string} [opt_options.flipVerticallyTipLabel] Label for vertical flip button
* @param {boolean} [opt_options.collapsed] Whether the control starts collapsed
*/
export class RotationControl extends Control {
constructor(opt_options) {
let options = opt_options || {};
options.collapsed = options.collapsed === true;
let tipLabel;
let label;
let label_;
label_ = document.createElement("span");
if (options.collapsed) {
label_.innerHTML = "»";
}
else {
label_.innerHTML = "«";
}
let collapseButton = document.createElement("button");
collapseButton.type = "button";
collapseButton.title = "Viewport rotation";
collapseButton.appendChild(label_);
let element = document.createElement("div");
element.className = "ol-rotation ol-control ol-unselectable";
let degree = document.createElement("span");
degree.innerHTML = "°";
degree.className = "ol-degree";
let rotationText = document.createElement("input");
rotationText.id = "rotationText";
rotationText.type = "text";
rotationText.value = 0;
rotationText.maxLength = 5;
rotationText.size = 1;
let rotationSlider = document.createElement("input");
rotationSlider.title = "Drag to rotate the image (Alt+Drag)";
rotationSlider.id = "rotation";
rotationSlider.type = "range";
rotationSlider.min = -180;
rotationSlider.max = 180;
rotationSlider.value = 0;
rotationSlider.step = 1;
tipLabel = options.resetTipLabel
? options.resetTipLabel
: "Reset rotation";
label = '<i class="fa fa-long-arrow-up" aria-hidden="true"></i>';
label_ = document.createElement("span");
label_.innerHTML = label;
let resetButton = document.createElement("button");
resetButton.type = "button";
resetButton.title = tipLabel;
resetButton.appendChild(label_);
tipLabel = options.flipHorizontallyTipLabel
? options.flipHorizontallyTipLabel
: "Flip horizontally";
label = '<i class="fa fa-code" aria-hidden="true"></i>';
label_ = document.createElement("span");
label_.innerHTML = label;
let flipHorizontalButton = document.createElement("button");
flipHorizontalButton.type = "button";
flipHorizontalButton.title = tipLabel;
flipHorizontalButton.appendChild(label_);
tipLabel = options.flipVerticallyTipLabel
? options.flipVerticallyTipLabel
: "Flip vertically";
label = '<i class="fa fa-code fa-rotate-90" aria-hidden="true"></i>';
label_ = document.createElement("span");
label_.innerHTML = label;
let flipVerticalButton = document.createElement("button");
flipVerticalButton.type = "button";
flipVerticalButton.title = tipLabel;
flipVerticalButton.appendChild(label_);
if (!options.collapsed) {
element.appendChild(rotationText);
element.appendChild(degree);
element.appendChild(rotationSlider);
element.appendChild(resetButton);
element.appendChild(flipHorizontalButton);
element.appendChild(flipVerticalButton);
}
element.appendChild(collapseButton);
super({
element: element,
target: options.target,
});
this.collapsed = options.collapsed;
let localChange = false;
const handleInput = function (e) {
localChange = true;
e.preventDefault();
e.stopPropagation();
let t = rotationText.value.replace(/[^\d-]/g, "");
if (t == "-") {
return;
}
if (t == "") {
t = 0;
}
let v = parseInt(t);
var da = v % 360;
v = ((2 * da) % 360) - da;
rotationText.value = v;
rotationSlider.value = v;
resetButton.firstChild.firstChild.style = `transform: rotate(${v}deg)`;
this.pmaViewport.setPosition({ rotation: v * 0.0174532925 });
localChange = false;
};
const handleRotation = function (e) {
if (localChange) {
return;
}
let v = Math.floor(
this.pmaViewport.getPosition().rotation / 0.0174532925
);
var da = v % 360;
v = ((2 * da) % 360) - da;
rotationText.value = v;
rotationSlider.value = v;
resetButton.firstChild.firstChild.style = `transform: rotate(${v}deg)`;
if (this.pmaViewport.getFlip().horizontally) {
flipHorizontalButton.classList.add("selected");
} else {
flipHorizontalButton.classList.remove("selected");
}
if (this.pmaViewport.getFlip().vertically) {
flipVerticalButton.classList.add("selected");
}
else {
flipVerticalButton.classList.remove("selected");
}
};
const handleReset = function (e) {
e.preventDefault();
e.stopPropagation();
rotationText.value = 0;
rotationSlider.value = 0;
resetButton.firstChild.firstChild.style = `transform: rotate(0deg)`;
this.pmaViewport.setPosition({ rotation: 0 });
resetButton.blur();
resetButton.hideFocus = true;
resetButton.style.outline = "none";
};
const handleFlipHorizontally = function (e) {
e.preventDefault();
e.stopPropagation();
this.pmaViewport.setFlip(
!this.pmaViewport.getFlip().horizontally,
this.pmaViewport.getFlip().vertically
);
if (this.pmaViewport.getFlip().horizontally) {
flipHorizontalButton.classList.add("selected");
} else {
flipHorizontalButton.classList.remove("selected");
}
flipHorizontalButton.blur();
flipHorizontalButton.hideFocus = true;
flipHorizontalButton.style.outline = "none";
};
const handleFlipVertically = function (e) {
e.preventDefault();
e.stopPropagation();
this.pmaViewport.setFlip(
this.pmaViewport.getFlip().horizontally,
!this.pmaViewport.getFlip().vertically
);
if (this.pmaViewport.getFlip().vertically) {
flipVerticalButton.classList.add("selected");
}
else {
flipVerticalButton.classList.remove("selected");
}
flipVerticalButton.blur();
flipVerticalButton.hideFocus = true;
flipVerticalButton.style.outline = "none";
};
this.collapseControl = function (e) {
if (e) {
e.preventDefault();
e.stopPropagation();
}
this.collapsed = !this.collapsed;
if (this.collapsed) {
element.removeChild(flipVerticalButton);
element.removeChild(flipHorizontalButton);
element.removeChild(resetButton);
element.removeChild(rotationSlider);
element.removeChild(degree);
element.removeChild(rotationText);
collapseButton.firstChild.innerHTML = "»";
}
else {
element.insertBefore(flipVerticalButton, element.firstChild);
element.insertBefore(flipHorizontalButton, element.firstChild);
element.insertBefore(resetButton, element.firstChild);
element.insertBefore(rotationSlider, element.firstChild);
element.insertBefore(degree, element.firstChild);
element.insertBefore(rotationText, element.firstChild);
collapseButton.firstChild.innerHTML = "«";
}
};
let handleChange = function (e) {
localChange = true;
e.preventDefault();
e.stopPropagation();
rotationText.value = rotationSlider.value;
resetButton.firstChild.firstChild.style = `transform: rotate(${rotationSlider.value}deg)`;
this.pmaViewport.setPosition({
rotation: rotationSlider.value * 0.0174532925,
});
localChange = false;
};
this.pmaViewport = options.pmaViewport;
rotationSlider.addEventListener(
"input",
handleChange.bind(this),
false
);
resetButton.addEventListener("click", handleReset.bind(this), false);
collapseButton.addEventListener("click", this.collapseControl.bind(this), false);
flipHorizontalButton.addEventListener(
"click",
handleFlipHorizontally.bind(this),
false
);
flipVerticalButton.addEventListener(
"click",
handleFlipVertically.bind(this),
false
);
rotationText.addEventListener("input", handleInput.bind(this), false);
this.pmaViewport.listen("viewchanged", handleRotation.bind(this));
}
/**
* Sets the OpenLayers map this control handles. This is automatically called by OpenLayers
* @param {ol.Map} map
*/
setMap(map) {
super.setMap(map);
}
/**
* Gets the collapsed state of the control
* @return {boolean} True if the control is currently collapsed
*/
getCollapsed() {
return this.collapsed;
}
/**
* Sets the collapsed state of the control
* @param {boolean} collapsed - True to collapse the control, otherwise false
*/
setCollapsed(collapsed) {
if (this.getCollapsed() != collapsed) {
this.collapseControl();
}
}
}