import { Events } from './components';
import { Events as ViewEvents } from '../../view/definitions';
import { rotate } from 'ol/coordinate';
/**
* Automatically handles syncronization of views between slides
* @param {SlideLoader[]} slideLoaders - Array of PMA.UI.Components.SlideLoaders.
*/
export class SyncView {
constructor(slideLoaders) {
if (!slideLoaders.length) {
console.error("Expected array of PMA.UI.Components.SlideLoader");
return;
}
this.slideLoaders = slideLoaders;
// for syncing viewers
this.eventsKeys = [];
this.posSync = [];
this.overridePosition = false;
this.listeners = {};
this.listeners[Events.SyncChanged] = [];
for (var i = 0; i < this.slideLoaders.length; i++) {
this.slideLoaders[i].listen(Events.BeforeSlideLoad, this.disableSync.bind(this));
}
}
/**
* Enables synchronization on the slides
* @fires PMA.UI.Components.Events#SyncChanged
*/
enableSync() {
this.posSync = [];
for (var i = 0; i < this.slideLoaders.length; i++) {
var slideLoader = this.slideLoaders[i];
if (slideLoader.mainViewport && slideLoader.mainViewport.map) {
this.posSync.push(slideLoader.mainViewport.getPosition());
var parameter = { index: i, self: this, slideLoaders: this.slideLoaders };
this.eventsKeys.push({ viewport: slideLoader.mainViewport, callback: viewChanged.bind(this, parameter) });
slideLoader.mainViewport.listen(ViewEvents.ViewChanged, this.eventsKeys[this.eventsKeys.length - 1].callback);
}
}
this.fireEvent(Events.SyncChanged, true);
}
/**
* Disables synchronization on the slides
* @fires PMA.UI.Components.Events#SyncChanged
*/
disableSync() {
if (this.eventsKeys) {
while (this.eventsKeys.length > 0) {
var ek = this.eventsKeys.pop();
var result = ek.viewport.unlisten(ViewEvents.ViewChanged, ek.callback);
}
}
this.posSync = [];
this.fireEvent(Events.SyncChanged, false);
}
/**
* Returns a value indicating whether slides are synchronized
* @fires PMA.UI.Components.Events#SyncChanged
*/
getStatus() {
return this.eventsKeys && this.eventsKeys.length > 0;
}
/**
* Attaches an event listener
* @param {PMA.UI.Components.Events} eventName - The name of the event to listen to
* @param {function} callback - The function to call when the event occurs
*/
listen(eventName, callback) {
if (!this.listeners.hasOwnProperty(eventName)) {
console.error(eventName + " is not a valid event");
}
this.listeners[eventName].push(callback);
}
// fires an event
fireEvent(eventName, eventArgs) {
if (!this.listeners.hasOwnProperty(eventName)) {
console.error(eventName + " does not exist");
return;
}
for (var i = 0, max = this.listeners[eventName].length; i < max; i++) {
this.listeners[eventName][i].call(this, eventArgs);
}
}
}
var overridePosition = false;
function viewChanged(parameters) {
if (parameters && !overridePosition) {
var self = parameters.self;
var slideLoader = parameters.slideLoaders[parameters.index];
let flipState = slideLoader.mainViewport.getFlip();
for (let i = 0; i < parameters.slideLoaders.length; i++) {
if (parameters.index == i) {
continue;
}
let sl = parameters.slideLoaders[i];
let flipStateI = sl.mainViewport.getFlip();
if (flipStateI.horizontally != flipState.horizontally || flipStateI.vertically != flipState.vertically) {
sl.mainViewport.setFlip(flipState.horizontally, flipState.vertically);
}
}
var pos = slideLoader.mainViewport.getPosition();
var oldPos = self.posSync[parameters.index];
if (isNaN(pos.zoom)) {
return;
}
if (oldPos) {
var diff = {
zoom: pos.zoom - oldPos.zoom,
rotation: pos.rotation - oldPos.rotation,
center: [pos.center[0] - oldPos.center[0], pos.center[1] - oldPos.center[1]]
};
self.posSync[parameters.index] = pos;
oldPos = self.posSync[parameters.index];
overridePosition = true;
for (var i = 0; i < parameters.slideLoaders.length; i++) {
if (i == parameters.index) {
continue;
}
var p = self.posSync[i];
if (p) {
p.zoom += diff.zoom;
p.rotation += diff.rotation;
if (p.rotation != oldPos.rotation) {
// different rotation
var d = rotate([diff.center[0], diff.center[1]], p.rotation - oldPos.rotation);
p.center[0] += d[0];
p.center[1] += d[1];
}
else {
p.center[0] += diff.center[0];
p.center[1] += diff.center[1];
}
parameters.slideLoaders[i].mainViewport.setPosition(p, true);
parameters.slideLoaders[i].mainViewport.map.getView().dispatchEvent("change:center");
}
self.posSync[i] = p;
}
overridePosition = false;
}
}
}