import {Selector} from "./olqv_selector.js";
import {DOMAccessor} from "./domelements.js";
import { FITS_HEADER } from "./fitsheader.js";
import {getUniqueId} from "./utils.js";
class Viewer {
static enter(what) {
console.group(this.name + "." + what);
}
static exit() {
console.groupEnd();
}
/**
*
* @param {*} relFITSFilePath
* @param {*} width
* @param {*} height
* @param {*} divId
* @param {*} canvasId
* @param {*} coordinatesFormatter
* @param {*} infosBlock
*/
constructor(relFITSFilePath, width, height, divId, canvasId, coordinatesFormatter, infosBlock) {
Viewer.enter(this.constructor.name);
this.relFITSFilePath = relFITSFilePath;
this.width = width;
this.height = height;
this.extent = [0, 0, width-1, height-1];
this.divId = divId;
this.canvas = document.getElementById(canvasId);
this.coordinatesFormatter = coordinatesFormatter;
this._interactionListeners = [];
//this.addInteractionListener = this.addInteractionListener.bind(this);
/*
** This is the layer which will contain the image
*/
this.layer = null;
/*
** This the layers group for shapes ( Boxes, Markers, Contours...)
*/
this._shapesLayerGroup = new ol.layer.Group({
layers : []
});
this._shapesLayerGroup.set('title', 'shapes');
/*
** Coordinates and grid
*/
this.graticule = null;
this.canvas.width = width;
this.canvas.height = height;
/*
** A pure pixel projection
*/
this.projection = new ol.proj.Projection({
code: 'local_image',
units: 'pixels',
extent: this.extent,
worldExtent: [...this.extent]
});
/*
** So far the controls are :
** * the display of coordinates and possibly some other related infos as the mouse moves over the image
** * the mode fullscreen
** *
** * If coordinatesFormatter is null, coordinates are not displayed
** *
** * Fullscreen mode is displayed in element with id = fullscreen if it exists (2D)
** *
*/
let fullscreen_source = "fullscreen";
if(document.getElementById(fullscreen_source) === null){
fullscreen_source = "";
}
if(this.coordinatesFormatter !== null){
this.controls = [
new ol.control.MousePosition({
undefinedHTML: '',
coordinateFormat: this.coordinatesFormatter.format.bind(this.coordinatesFormatter)
}),
new ol.control.FullScreen({ source: fullscreen_source })
];
}else{
this.controls = [
new ol.control.FullScreen({ source: fullscreen_source })
];
}
this.map = new ol.Map({
interactions: ol.interaction.defaults({mouseWheelZoom:false}),
target: this.divId,
view: new ol.View({
projection: this.projection,
center: ol.extent.getCenter(this.extent),
//resolution: 1,
constrainOnlyCenter: true,
showFullExtent: true,
zoom : 1,
//resolution: this.canvas.width / 512,
}),
controls: [],
layers : [this._shapesLayerGroup]
});
// prevent filtering on zoomed image
this.map.on('precompose', function(evt) {
evt.context.imageSmoothingEnabled = false;
evt.context.webkitImageSmoothingEnabled = false;
evt.context.mozImageSmoothingEnabled = false;
evt.context.msImageSmoothingEnabled = false;
});
// ctrl+wheel to zoom
const mouseWheelInt = new ol.interaction.MouseWheelZoom({
useAnchor : false
});
this.map.addInteraction(mouseWheelInt);
this.map.on('wheel', function(evt) {
mouseWheelInt.setActive(ol.events.condition.platformModifierKeyOnly(evt));
});
this._infosBlock = infosBlock;
this.selector = new Selector(this);
let target = this.map.getTarget();
this._jTarget = typeof target === "string" ? $("#" + target) : $(target);
this.sliceRange = null;
this.dataSteps = null;
this.statistics = null;
//document.getElementById(divId).addEventListener("focus", () => { this.enableControls(); this._hasMouse = true; } );
document.getElementById(divId).addEventListener("mouseenter", () => {this.enableControls(); this._hasMouse = true;} );
document.getElementById(divId).addEventListener("mouseleave", () => {this.disableControls(); this._hasMouse = false;} );
this.map.on("pointerdrag", (event) => {
if(event.pointerEvent.buttons !== 1 && event.pointerEvent.buttons !== 4){
event.preventDefault();
}
});
this._initialResolution = this.map.getView().getResolution()
this._hasMouse = false;
this._currentInteraction = undefined;
this._currentCursor = undefined;
Viewer.exit();
}
addClickEvent(callback){
this.map.on("click", (event) => {
if(event.pointerEvent.buttons > 1){
event.preventDefault();
}
callback(event)
});
}
isInExtent(x, y){
if(x > this.extent[0] &&
x < this.extent[2] &&
y > this.extent[1] &&
y < this.extent[3] ){
return true;
}
return false;
}
disableControls() {
Viewer.enter(this.disableControls.name);
if (this.controls) {
this.controls.forEach((control) => {
this.map.removeControl(control);
});
}
Viewer.exit();
}
enableControls() {
Viewer.enter(this.enableControls.name);
if (this.controls) {
this.controls.forEach((control) => {
this.map.addControl(control);
});
}
Viewer.exit();
}
get infosBlock() { return this._infosBlock; }
/*
** A getter for the LayerGroup dedicated to the shapes.
*/
get shapesLayerGroup() {
return this._shapesLayerGroup;
}
/*
** add a Layer to the shapesLayerGroup
*/
addShapesLayer(layer) {
this._shapesLayerGroup.getLayers().getArray().push(layer);
}
getDivId() {
return this.divId;
}
getRelFITSFilePath() {
return this.relFITSFilePath;
}
getMap() {
return this.map;
}
getStatistics() {
return this.statistics;
}
getSliceRange() {
return this.sliceRange;
}
reset() {
this.map.getView().setCenter(ol.extent.getCenter(this.extent));
this.map.getView().setResolution(this._initialResolution);
}
imageLoadFunction(image, src) {
Viewer.enter(this.imageLoadFunction.name);
DOMAccessor.getLoading().style.display = 'block';
image.getImage().addEventListener("load", () => {
Viewer.enter("Listener : image loaded, draw it!");
DOMAccessor.getLoading().style.display = 'none';
this.canvas.getContext('2d').drawImage(image.getImage(), 0, 0);
Viewer.exit();
});
image.getImage().src = src;
image.getImage().crossOrigin = "Anonymous";
Viewer.exit();
}
display(imageURL, sliceRange, dataSteps, statistics) {
Viewer.enter(this.display.name);
this.sliceRange = sliceRange;
if(this.coordinatesFormatter !== null)
this.coordinatesFormatter.setDataSteps(dataSteps);
this.statistics = statistics;
if (this.layer) {
this.map.removeLayer(this.layer);
}
this.layer = new ol.layer.Image({
source: new ol.source.ImageStatic({
url: imageURL,
projection: this.projection,
imageExtent: this.extent,
imageLoadFunction: this.imageLoadFunction.bind(this)
})
});
this.map.addLayer(this.layer);
this.map.getView().fit(this.extent, {size:this.map.getSize(), maxZoom:16})
Viewer.exit();
}
getCoordinatesFormatter() {
return this.coordinatesFormatter;
}
getSelector() {
return this.selector;
}
is3D() {
return FITS_HEADER.dimensionality() == 3;
}
is2D() {
return FITS_HEADER.dimensionality() == 2;
}
numDims() {
return FITS_HEADER.dimensionality();
}
couple(viewer) {
var updateView = function (event, viewRef) {
let newValue = event.target.get(event.key);
viewRef.set(event.key, newValue);
};
this.map.getView().on('change:resolution', function (event) {
updateView(event, viewer.getMap().getView());
});
this.map.getView().on('change:center', function (event) {
updateView(event, viewer.getMap().getView());
});
}
set cursor(kursor) {
Viewer.enter("set cursor");
this._cursor = kursor;
this._jTarget.css('cursor', kursor);
Viewer.exit();
}
setCurrentInteraction(interaction, cursor) {
this.notifyInteractionListeners();
this._currentInteraction = interaction;
this._currentCursor = cursor;
}
removeCurrentInteraction() {
if (this._currentInteraction) {
this.map.removeInteraction(this._currentInteraction);
this._currentInteraction = undefined;
this.cursor = 'default';
}
}
stopCurrentInteraction() {
if (this._currentInteraction) {
this.map.removeInteraction(this._currentInteraction);
}
}
startCurrentInteraction() {
if (this._currentInteraction && this._currentCursor) {
this.map.addInteraction(this._currentInteraction);
this.cursor = this._currentCursor;
}
}
restoreDefaultInteraction() {
this.setCurrentInteraction(this.selector.interaction, this.selector.cursor);
this.startCurrentInteraction();
}
hasCurrentInteraction(){
if(this._currentInteraction !== undefined){
return true;
}
return false;
}
addInteractionListener(listener){
this._interactionListeners.push(listener);
}
removeInteractionListener(listener){
this._interactionListeners.splice(this._interactionListeners.indexOf(listener), 1);
}
notifyInteractionListeners(){
for(let listener of this._interactionListeners){
listener.interactionChanged();
}
}
get currentInteraction() {
return this._currentInteraction;
}
get defaultInteraction() {
return this.selector.interaction;
}
get defaultCursor() {
return this.selector.cursor;
}
get maxIndexes() {
return [this.width-1, this.height-1];
}
get hasMouse() { return this._hasMouse; }
set hasMouse(b) { this._hasMouse = b; }
}
export{
Viewer
}