diff --git a/examples/al-save-colormap.html b/examples/al-save-colormap.html index 384e9666..a557c741 100644 --- a/examples/al-save-colormap.html +++ b/examples/al-save-colormap.html @@ -25,9 +25,9 @@ aladin.setImageLayer(survey2); - /*setTimeout(() => { + setTimeout(() => { aladin.removeHiPSFromFavorites(survey3) - }, 10000);*/ + }, 5000); aladin.addColormap('mycmap', ["lightblue", "red", "violet", "lightgreen"]) diff --git a/src/core/src/renderable/mod.rs b/src/core/src/renderable/mod.rs index 5a116a8a..e397d296 100644 --- a/src/core/src/renderable/mod.rs +++ b/src/core/src/renderable/mod.rs @@ -326,6 +326,7 @@ impl Layers { .ok_or(err_layer_not_found)?; self.layers.remove(id_layer); + al_core::log(&format!("remove layer {:?}", id_layer)); // Loop over all the meta for its longitude reversed property // and set the camera to it if there is at least one let longitude_reversed = self.meta.values().any(|meta| meta.longitude_reversed); @@ -335,9 +336,13 @@ impl Layers { // Check if the url is still used let id_still_used = self.ids.values().any(|rem_id| rem_id == &id); if id_still_used { + al_core::log("still used"); + // Keep the resource whether it is a HiPS or a FITS Ok(id_layer) } else { + al_core::log("not needed"); + // Resource not needed anymore if let Some(hips) = self.hipses.remove(&id) { // A HiPS has been found and removed diff --git a/src/js/Aladin.js b/src/js/Aladin.js index dd023716..2c07a05d 100644 --- a/src/js/Aladin.js +++ b/src/js/Aladin.js @@ -424,12 +424,11 @@ export let Aladin = (function () { } // at least id or url is defined - let key = id || url; + let key = name || id || url; // Merge what is already in the cache for that HiPS with new properties // coming from the MOCServer - let hips = new HiPS(key, key, cachedSurvey) - self.hipsCache.append(key, hips); + self.hipsCache.append(key, cachedSurvey); } }; this._setupUI(options); @@ -1443,9 +1442,11 @@ export let Aladin = (function () { }; Aladin.prototype.removeUIByName = function(name) { - let elt = this.ui.find((elm) => elm.name === name) - if (elt) { - elt.remove() + let index = this.ui.findIndex((elm) => elm.name === name) + if (index >= 0) { + this.ui[index].remove(); + + this.ui.splice(index, 1); } }; @@ -1540,11 +1541,12 @@ export let Aladin = (function () { maxOrder, options ) { - let hips = new HiPS(id, url || id, { name, maxOrder, url, cooFrame, ...options }) + let hipsOptions = { id, name, maxOrder, url, cooFrame, ...options }; + let hips = new HiPS(id, url || id, hipsOptions) - if (this instanceof Aladin && !this.hipsCache.contains(id)) { + if (this instanceof Aladin && !this.hipsCache.contains(hips.name)) { // Add it to the cache as soon as possible if we have a reference to the aladin object - this.hipsCache.append(hips.id, hips) + this.hipsCache.append(hips.name, hipsOptions) } return hips; @@ -1591,11 +1593,14 @@ export let Aladin = (function () { console.warn(survey + ' is among the list of HiPS currently in the view.'); } + let id; if (typeof survey !== "string") { - survey = survey.id; + id = survey.name + } else { + id = survey } - this.hipsCache.delete(survey); + this.hipsCache.delete(id); } /** @@ -1847,9 +1852,9 @@ export let Aladin = (function () { const idOrUrl = urlOrHiPSOrFITS; // many cases here // 1/ It has been already added to the cache - let cachedLayer = hipsCache.get(idOrUrl) - if (cachedLayer) { - imageLayer = cachedLayer + let cachedOptions = hipsCache.get(idOrUrl) + if (cachedOptions) { + imageLayer = A.HiPS(idOrUrl, cachedOptions); } else { // 2/ Not in the cache, then we create the hips from this url/id and // go to the case 3 @@ -1860,18 +1865,20 @@ export let Aladin = (function () { // 3/ It is an image survey. imageLayer = urlOrHiPSOrFITS; - let cachedLayer = hipsCache.get(imageLayer.id) - if (!cachedLayer) { - hipsCache.append(imageLayer.id, imageLayer) + let cachedLayerOptions = hipsCache.get(imageLayer.name) + + if (!cachedLayerOptions) { + hipsCache.append(imageLayer.name, imageLayer.options) } else { // first set the options of the cached layer to the one of the user - cachedLayer.setOptions(imageLayer.options) // if it is in the cache we get it from the cache - imageLayer = cachedLayer + imageLayer = A.HiPS(imageLayer.id, cachedLayerOptions) } } + let imageLayerCopied = Object.assign(Object.create(Object.getPrototypeOf(imageLayer)), imageLayer) + imageLayerCopied.layer = layer; - return this.view.setOverlayImageLayer(imageLayer, layer); + return this.view.setOverlayImageLayer(imageLayerCopied, layer); }; /** diff --git a/src/js/DefaultHiPSList.js b/src/js/DefaultHiPSList.js index 699ac77d..4bf19789 100644 --- a/src/js/DefaultHiPSList.js +++ b/src/js/DefaultHiPSList.js @@ -153,7 +153,7 @@ export let HiPSList = (function () { { creatorDid: "ivo://CDS/P/allWISE/color", id: "P/allWISE/color", - name: "AllWISE color", + name: "AllWISE color Red (W4) , Green (W2) , Blue (W1) from raw Atlas Images", maxOrder: 8, tileSize: 512, imgFormat: "jpeg", diff --git a/src/js/HiPS.js b/src/js/HiPS.js index 1c382585..da71d385 100644 --- a/src/js/HiPS.js +++ b/src/js/HiPS.js @@ -194,7 +194,7 @@ export let HiPS = (function () { this.id = id; this.options = options; - this.name = (options && options.name) || undefined; + this.name = (options && options.name) || id; this.startUrl = options.startUrl; this.slice = 0; @@ -949,8 +949,8 @@ export let HiPS = (function () { let self = this; let hipsCache = this.view.aladin.hipsCache; - if (hipsCache.contains(self.id)) { - hipsCache.append(self.id, this) + if (hipsCache.contains(self.name)) { + hipsCache.append(self.name, this.options) } }; diff --git a/src/js/HiPSCache.js b/src/js/HiPSCache.js index ca62d40e..b34ea41b 100644 --- a/src/js/HiPSCache.js +++ b/src/js/HiPSCache.js @@ -36,8 +36,8 @@ export let HiPSCache = (function () { /* * key can be a CDS ID or an url. TODO could be an options.name too. */ - HiPSCache.prototype.append = function (key, image) { - this.cache[key] = image; + HiPSCache.prototype.append = function (key, options) { + this.cache[key] = options; ALEvent.HIPS_CACHE_UPDATED.dispatchedTo(document.body); }; diff --git a/src/js/View.js b/src/js/View.js index c9aeefe5..ad4e2f69 100644 --- a/src/js/View.js +++ b/src/js/View.js @@ -1830,6 +1830,7 @@ export let View = (function () { View.prototype.removeImageLayer = function (layer) { // Get the survey to remove to dissociate it from the view let imageLayer = this.imageLayers.get(layer); + if (imageLayer === undefined) { // there is nothing to remove return; diff --git a/src/js/gui/Box/HiPSBrowserBox.js b/src/js/gui/Box/HiPSBrowserBox.js index ab36d969..29aa5ecc 100644 --- a/src/js/gui/Box/HiPSBrowserBox.js +++ b/src/js/gui/Box/HiPSBrowserBox.js @@ -63,26 +63,31 @@ export class HiPSBrowserBox extends Box { self._filterHiPSList({}) }); + + const _parseHiPS = (e) => { const value = e.target.value; - let image; + let image, name; // A user can put an url try { image = new URL(value).href; + name = image; } catch (e) { // Or he can select a HiPS from the list given const hips = HiPSBrowserBox.HiPSList[value]; if (hips) { image = hips.ID || hips.hips_service_url; + name = hips.obs_title || hips.ID; } else { // Finally if not found, interpret the input text value as the HiPS (e.g. ID) image = value; + name = value; } } if (image) { - self._addHiPS(image) + self._addHiPS(image, name) self.searchDropdown.update({title: value}); } }; @@ -116,6 +121,11 @@ export class HiPSBrowserBox extends Box { searchDropdown.removeClass('aladin-valid') searchDropdown.removeClass('aladin-not-valid') }, + change(e) { + e.stopPropagation(); + e.preventDefault() + _parseHiPS(e) + } }, }); @@ -273,10 +283,11 @@ export class HiPSBrowserBox extends Box { }; } - _addHiPS(id) { - console.log("add hips", id) + _addHiPS(id, name) { let self = this; + let hips = A.imageHiPS(id, { + name, successCallback: (hips) => { self.searchDropdown.removeClass('aladin-not-valid'); self.searchDropdown.addClass('aladin-valid'); @@ -288,6 +299,8 @@ export class HiPSBrowserBox extends Box { } }) + self.aladin.removeUIByName("cube_displayer" + hips.layer) + if (!hips.cubeDepth) return; @@ -321,10 +334,10 @@ export class HiPSBrowserBox extends Box { hips.setSliceNumber(idxSlice) cubeDisplayer.update({position: cubeDisplayer.position, content: Layout.horizontal([prevBtn, nextBtn, slicer, toStr(idxSlice + 1, true) + '/' + toStr(numSlices, false)])}) }; - + let slicer = Input.slider({ label: "Slice", - name: "cube slicer", + name: "cube_slicer" + hips.layer, ticks: [idxSlice], tooltip: {content: (idxSlice + 1) + '/' + numSlices, position: {direction: 'bottom'}}, min: 0, @@ -370,7 +383,7 @@ export class HiPSBrowserBox extends Box { let cubeDisplayer = A.box({ close: true, - name: 'player' + hips.name, + name: "cube_displayer" + hips.layer, header: { title: 'Player for: ' + hips.name, draggable: true, @@ -378,6 +391,7 @@ export class HiPSBrowserBox extends Box { content: Layout.horizontal([prevBtn, nextBtn, slicer, toStr(idxSlice + 1, true) + '/' + toStr(numSlices, false)]), position: {anchor: 'center top'}, }); + self.aladin.addUI(cubeDisplayer) }, errorCallback: (e) => { diff --git a/src/js/gui/Box/HiPSSettingsBox.js b/src/js/gui/Box/HiPSSettingsBox.js index 380b1cdd..3185f9ef 100644 --- a/src/js/gui/Box/HiPSSettingsBox.js +++ b/src/js/gui/Box/HiPSSettingsBox.js @@ -28,7 +28,6 @@ * *****************************************************************************/ import { Form } from "../Widgets/Form.js"; -import { ColorCfg } from "../../ColorCfg.js"; import { Box } from "../Widgets/Box.js"; import { ALEvent } from "../../events/ALEvent.js"; import opacityIconUrl from '../../../../assets/icons/opacity.svg'; @@ -165,6 +164,21 @@ import { ColorCfg } from "../../ColorCfg.js"; slider.update({value: contrast, tooltip: {content: `${contrast.toFixed(3)}`, position: {direction: 'right'}}}) } }, + { + label: 'gamma:', + tooltip: {content: 'gamma', position: {direction: 'right'}}, + name: 'gamma', + type: 'range', + min: 0.1, + max: 10.0, + ticks: [1.0], + value: 1.0, + change: (e, slider) => { + const gamma = +e.target.value + self.options.layer.setGamma(gamma) + slider.update({value: gamma, tooltip: {content: `${gamma.toFixed(3)}`, position: {direction: 'right'}}}) + } + }, ] }); let pixelSettingsContent = new Form({ @@ -274,6 +288,7 @@ import { ColorCfg } from "../../ColorCfg.js"; this.opacitySettingsContent.set('opacity', hips.getOpacity()); this.luminositySettingsContent.set('brightness', colorCfg.getBrightness()); this.luminositySettingsContent.set('contrast', colorCfg.getContrast()); + this.luminositySettingsContent.set('gamma', colorCfg.getGamma()); this.luminositySettingsContent.set('saturation', colorCfg.getSaturation()); } @@ -305,6 +320,7 @@ import { ColorCfg } from "../../ColorCfg.js"; this.opacitySettingsContent.set('opacity', hips.getOpacity()); this.luminositySettingsContent.set('brightness', colorCfg.getBrightness()); this.luminositySettingsContent.set('contrast', colorCfg.getContrast()); + this.luminositySettingsContent.set('gamma', colorCfg.getGamma()); this.luminositySettingsContent.set('saturation', colorCfg.getSaturation()); } }); diff --git a/src/js/gui/Box/StackBox.js b/src/js/gui/Box/StackBox.js index 0ddf4f53..f7eede7f 100644 --- a/src/js/gui/Box/StackBox.js +++ b/src/js/gui/Box/StackBox.js @@ -721,11 +721,14 @@ export class OverlayStackBox extends Box { self.cachedHiPS = {}; for (var key in hipsCache.cache) { - let HiPS = hipsCache.cache[key]; + let HiPSOptions = hipsCache.cache[key]; - if (HiPS.name) { - self.cachedHiPS[HiPS.name.toString()] = HiPS; - } + /*if (HiPSOptions.name) { + self.cachedHiPS[HiPSOptions.name.toString()] = HiPSOptions; + } else { + self.cachedHiPS[key] = HiPSOptions; + }*/ + self.cachedHiPS[key] = HiPSOptions; } // Update the options of the selector @@ -739,7 +742,10 @@ export class OverlayStackBox extends Box { let currentHiPS = hips.HiPSSelector.options.value let favoritesCopy = [...favorites]; - if (!(currentHiPS in favoritesCopy)) { + + // add the current hips to the selector as well, even if it has been manually + // removed from the HiPSList + if (favoritesCopy.indexOf(currentHiPS) < 0) { favoritesCopy.push(currentHiPS) } @@ -935,25 +941,25 @@ export class OverlayStackBox extends Box { hipsOptions.sort() for (const layer of layers) { - let HiPSSelector = Input.select({ - value: layer.name, + value: layer.name || layer.id, options: hipsOptions, title: layer.name, change: (e) => { let name = e.target.value; // search for the - let HiPS = self.cachedHiPS[name]; + let HiPSOptions = self.cachedHiPS[name]; - let image; + /*let image; if (HiPS instanceof Image) { image = HiPS; } else { // HiPS image = HiPS.id || HiPS.url || undefined; - } + }*/ + let hips = A.HiPS(HiPSOptions.id || HiPSOptions.url, HiPSOptions); - self.aladin.setOverlayImageLayer(image, layer.layer); + self.aladin.setOverlayImageLayer(hips, layer.layer); } }); @@ -963,9 +969,10 @@ export class OverlayStackBox extends Box { disable: layer.layer === "base", tooltip: { content: "Remove", position: { direction: "top" } }, action(e) { + console.log(layer) self.aladin.removeImageLayer(layer.layer); // remove HiPS cube player if any - self.aladin.removeUIByName("player" + layer.name) + self.aladin.removeUIByName("cube_displayer" + layer.layer) }, }); @@ -1000,11 +1007,9 @@ export class OverlayStackBox extends Box { }); let settingsBox = new HiPSSettingsBox(self.aladin); - settingsBox.update({ layer }); settingsBox._hide(); - let settingsBtn = new TogglerActionButton({ icon: { url: settingsIconUrl, monochrome: true }, size: "small", diff --git a/src/js/gui/Widgets/Widget.js b/src/js/gui/Widgets/Widget.js index 74823e24..a9da7a23 100644 --- a/src/js/gui/Widgets/Widget.js +++ b/src/js/gui/Widgets/Widget.js @@ -74,6 +74,7 @@ export class DOMElement { if (target && target.children) { index = Array.prototype.indexOf.call(target.children, el); } + console.log("remove", el) el.remove() return {target, position: index};