// Copyright 2013 - UDS/CNRS // The Aladin Lite program is distributed under the terms // of the GNU General Public License version 3. // // This file is part of Aladin Lite. // // Aladin Lite 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, version 3 of the License. // // Aladin Lite 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. // // The GNU General Public License is available in COPYING file // along with Aladin Lite. // /****************************************************************************** * Aladin Lite project * * File gui/Stack.js * * * Author: Matthieu Baumann[CDS] * *****************************************************************************/ import { HpxImageSurvey } from "../HpxImageSurvey.js"; import { ALEvent } from "../events/ALEvent.js"; import { HiPSSelector } from "./HiPSSelector.js"; import { Color } from "./../Color.js"; import { Utils } from './../Utils.js'; export class HiPSLayer { // Constructor constructor(aladin, view, survey) { this.aladin = aladin; this.view = view; this.survey = survey; this.hidden = false; this.lastOpacity = 1.0; // HiPS header div if (this.survey.layer === "base") { this.headerDiv = $( '
' + ' ' + '' + '' + '' + '
' ); } else { this.headerDiv = $( '
' + ' ' + '' + '' + '' + '' + '
' ); } // HiPS main options div let cmListStr = ''; for (const cm of this.aladin.webglAPI.getAvailableColormapList()) { cmListStr += ''; } // Add the native which is special: // - for FITS hipses, it is changed to grayscale // - for JPG/PNG hipses, we do not use any colormap in the backend this.nameRadioColorChoice = encodeURIComponent(Utils.uuidv4()); cmListStr += ''; this.mainDiv = $(''); this._addListeners(); this._updateHiPSLayerOptions(); let self = this; this.layerChangedListener = function(e) { const survey = e.detail.survey; if (survey.layer === self.survey.layer) { // Update the survey to the new one self.survey = survey; self._updateHiPSLayerOptions(); } self._updateSurveysDropdownList(); }; ALEvent.HIPS_LAYER_CHANGED.listenedBy(this.aladin.aladinDiv, this.layerChangedListener); } destroy() { ALEvent.HIPS_LAYER_CHANGED.remove(this.aladin.aladinDiv, this.layerChangedListener); this.mainDiv[0].removeEventListener("click", this.clickOnAladinFrameListener); } _addListeners() { const self = this; // HEADER DIV listeners // Click opener const clickOpener = this.headerDiv.find('.indicator'); clickOpener.unbind("click"); clickOpener.click(function () { if (clickOpener.hasClass('right-triangle')) { clickOpener.removeClass('right-triangle'); clickOpener.addClass('down-triangle'); self.mainDiv.slideDown(300); self.aladin.aladinDiv.dispatchEvent(new CustomEvent('select-layer', { detail: self.survey.layer })); } else { clickOpener.removeClass('down-triangle'); clickOpener.addClass('right-triangle'); self.mainDiv.slideUp(300); } }); // Click on aladin options should select the layer clicked let aladinOptionsFrame = self.mainDiv[0]; this.clickOnAladinFrameListener = function(e) { self.aladin.aladinDiv.dispatchEvent(new CustomEvent('select-layer', { detail: self.survey.layer })); }; aladinOptionsFrame.addEventListener("click", this.clickOnAladinFrameListener); // Update list of surveys self._updateSurveysDropdownList(); const surveySelector = this.headerDiv.find('.aladin-surveySelection'); surveySelector.unbind("change"); surveySelector.change(function () { let cfg = HpxImageSurvey.SURVEYS[$(this)[0].selectedIndex]; if (self.hidden) { cfg.options.opacity = 0.0; } const survey = self.aladin.createImageSurvey( cfg.id, cfg.name, cfg.url, undefined, cfg.maxOrder, cfg.options ); self.aladin.setOverlayImageLayer(survey, self.survey.layer); self.aladin.aladinDiv.dispatchEvent(new CustomEvent('select-layer', { detail: self.survey.layer })); }); // Search HiPS button const hipsSelector = this.headerDiv.find('.aladin-HiPSSelector'); hipsSelector.unbind("click"); hipsSelector.click(function () { if (!self.hipsSelector) { self.hipsSelector = new HiPSSelector(self.aladin.aladinDiv, (IDOrURL) => { const layerName = self.survey.layer; self.aladin.setOverlayImageLayer(IDOrURL, layerName); }, self.aladin); } self.hipsSelector.show(); }); // Delete HiPS button const deleteLayer = this.headerDiv.find('.aladin-delete-layer'); deleteLayer.unbind('click'); deleteLayer.click(function () { const removeLayerEvent = new CustomEvent('remove-layer', { detail: self.survey.layer }); self.aladin.aladinDiv.dispatchEvent(removeLayerEvent); }); // Hide HiPS button const hideLayer = this.headerDiv.find('.aladin-layer-hide'); hideLayer.unbind("click"); hideLayer.click(function () { self.hidden = !self.hidden; let opacitySlider = self.mainDiv.find('.opacity').eq(0); let newOpacity = 0.0; if (self.hidden) { self.lastOpacity = self.survey.getOpacity(); hideLayer.text(''); } else { newOpacity = self.lastOpacity; hideLayer.text('👁️'); } // Update the opacity slider opacitySlider.val(newOpacity); opacitySlider.get(0).disabled = self.hidden; self.survey.setOpacity(newOpacity); // Update HpxImageSurvey.SURVEYS definition /*const idxSelectedHiPS = self.headerDiv.find('.aladin-surveySelection')[0].selectedIndex; let surveyDef = HpxImageSurvey.SURVEYS[idxSelectedHiPS]; let options = surveyDef.options || {}; options.opacity = newOpacity; surveyDef.options = options;*/ }); // MAIN DIV listeners // blending method if (self.survey.layer === "base") { this.mainDiv.find('tr').eq(8).hide(); } else { const blendingSelector = this.mainDiv.find('.blending').eq(0); blendingSelector.unbind("change"); blendingSelector.change(function () { let mode = blendingSelector.val() self.survey.setBlendingConfig( mode === "Additive" ); }); } // image format const format4ImgLayer = this.mainDiv.find('.format').eq(0); const minCut4ImgLayer = this.mainDiv.find('.min-cut').eq(0); const maxCut4ImgLayer = this.mainDiv.find('.max-cut').eq(0); format4ImgLayer.unbind("change"); format4ImgLayer.change(function () { const imgFormat = format4ImgLayer.val(); self.survey.changeImageFormat(imgFormat); let minCut = 0; let maxCut = 255; if (imgFormat === "FITS") { // FITS format minCut = self.survey.properties.minCutout; maxCut = self.survey.properties.maxCutout; } self.survey.setCuts([minCut, maxCut]); // update the cuts only minCut4ImgLayer.val(parseFloat(minCut.toFixed(5))); maxCut4ImgLayer.val(parseFloat(maxCut.toFixed(5))); // update HpxImageSurvey.SURVEYS definition /*const idxSelectedHiPS = self.headerDiv.find('.aladin-surveySelection')[0].selectedIndex; let surveyDef = HpxImageSurvey.SURVEYS[idxSelectedHiPS]; let options = surveyDef.options || {}; options.minCut = minCut; options.maxCut = maxCut; options.imgFormat = imgFormat; surveyDef.options = options;*/ }); // min/max cut minCut4ImgLayer.unbind("input blur"); maxCut4ImgLayer.unbind("input blur"); minCut4ImgLayer.add(maxCut4ImgLayer).on('input blur', function (e) { let minCutValue = parseFloat(minCut4ImgLayer.val()); let maxCutValue = parseFloat(maxCut4ImgLayer.val()); if (isNaN(minCutValue) || isNaN(maxCutValue)) { return; } self.survey.setCuts([minCutValue, maxCutValue]); // update HpxImageSurvey.SURVEYS definition /*const idxSelectedHiPS = self.surveySelectionDiv[0].selectedIndex; let surveyDef = HpxImageSurvey.SURVEYS[idxSelectedHiPS]; let options = surveyDef.options || {}; options.minCut = minCutValue; options.maxCut = maxCutValue; surveyDef.options = options;*/ }); // colormap const colorMapSelect4ImgLayer = this.mainDiv.find('.colormap-selector').eq(0); const stretchSelect4ImgLayer = this.mainDiv.find('.stretch').eq(0); const reverseCmCb = this.mainDiv.find('.reversed').eq(0); const colorSelect4ImgLayer = self.mainDiv.find('.color-selector').eq(0); reverseCmCb.unbind("change"); colorMapSelect4ImgLayer.unbind("change"); stretchSelect4ImgLayer.unbind("change"); const colorMode = this.mainDiv[0].getElementsByClassName('colormap-color-selector'); colorMapSelect4ImgLayer.add(reverseCmCb).add(stretchSelect4ImgLayer).change(function () { const stretch = stretchSelect4ImgLayer.val(); if (colorMode[0].checked) { // Color map case const cmap = colorMapSelect4ImgLayer.val(); const reverse = reverseCmCb[0].checked; self.survey.setColormap(cmap, { reversed: reverse, stretch: stretch }); } else { // Single color case const colorHex = colorSelect4ImgLayer.val(); let colorRgb = Color.hexToRgb(colorHex); self.survey.setColor([colorRgb.r / 255.0, colorRgb.g / 255.0, colorRgb.b / 255.0, 1.0], { stretch: stretch }); } // update HpxImageSurvey.SURVEYS definition /*const idxSelectedHiPS = self.headerDiv.find('.aladin-surveySelection')[0].selectedIndex; let surveyDef = HpxImageSurvey.SURVEYS[idxSelectedHiPS]; let options = surveyDef.options || {}; options.colormap = cmap; options.stretch = stretch; options.reversed = reverse; surveyDef.options = options;*/ }); // Redefine the event for the newly added DOM colorSelect4ImgLayer.unbind("input"); colorSelect4ImgLayer.on('input', function () { const colorHex = colorSelect4ImgLayer.val(); let colorRgb = Color.hexToRgb(colorHex); self.survey.setColor([colorRgb.r / 255.0, colorRgb.g / 255.0, colorRgb.b / 255.0, 1.0]); }); // colormap/color radio const colorMapTr = this.mainDiv.find('tr').eq(1); const colorTr = this.mainDiv.find('tr').eq(2); const [colormapChoiceRadioBtn, colorChoiceRadioBtn] = document.querySelectorAll('input[name="' + this.nameRadioColorChoice + '"]'); $(colormapChoiceRadioBtn).on("click", function (e) { // set the colormap const cmap = colorMapSelect4ImgLayer.val(); self.survey.setColormap(cmap); }); $(colorChoiceRadioBtn).on("click", function (e) { // set the color const colorHex = colorSelect4ImgLayer.val(); let colorRgb = Color.hexToRgb(colorHex); self.survey.setColor([colorRgb.r / 255.0, colorRgb.g / 255.0, colorRgb.b / 255.0, 1.0]); }); // opacity const opacity4ImgLayer = self.mainDiv.find('.opacity').eq(0); opacity4ImgLayer.unbind("input"); opacity4ImgLayer.on('input', function () { const opacity = +opacity4ImgLayer.val(); self.survey.setOpacity(opacity); // update HpxImageSurvey.SURVEYS definition /*const idxSelectedHiPS = self.headerDiv.find('.aladin-surveySelection')[0].selectedIndex; let surveyDef = HpxImageSurvey.SURVEYS[idxSelectedHiPS]; let options = surveyDef.options || {}; options.opacity = opacity; surveyDef.options = options;*/ }); } _updateHiPSLayerOptions() { const colorModeTr = this.mainDiv.find('tr').eq(0); const colorMapTr = this.mainDiv.find('tr').eq(1); const colorTr = this.mainDiv.find('tr').eq(2); const reverseTr = this.mainDiv.find('tr').eq(3); const stretchTr = this.mainDiv.find('tr').eq(4); const formatTr = this.mainDiv.find('tr').eq(5); const minCutTr = this.mainDiv.find('tr').eq(6); const maxCutTr = this.mainDiv.find('tr').eq(7); const colorMode = this.mainDiv.find('.colormap-color-selector').eq(0); const reverseCmCb = this.mainDiv.find('.reversed').eq(0); const colorMapSelect4ImgLayer = this.mainDiv.find('.colormap-selector').eq(0); const stretchSelect4ImgLayer = this.mainDiv.find('.stretch').eq(0); const formatSelect4ImgLayer = this.mainDiv.find('.format').eq(0); const opacity4ImgLayer = this.mainDiv.find('.opacity').eq(0); const minCut = this.mainDiv.find('.min-cut').eq(0); const maxCut = this.mainDiv.find('.max-cut').eq(0); formatSelect4ImgLayer.empty(); this.survey.properties.formats.forEach(format => { formatSelect4ImgLayer.append($('