diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml
index 57160ccb..867f43c5 100644
--- a/.github/workflows/npm-publish.yml
+++ b/.github/workflows/npm-publish.yml
@@ -21,6 +21,7 @@ jobs:
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "$HOME/.cargo/env"
+ rustup default nightly
- name: "Install wasm-pack"
run: |
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -y
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 5e9c092e..cc5afb27 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -22,6 +22,7 @@ jobs:
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
source "$HOME/.cargo/env"
+ rustup default nightly
- name: "Install wasm-pack"
run: |
curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh -s -- -y
diff --git a/assets/icons/minus.svg b/assets/icons/minus.svg
new file mode 100644
index 00000000..bc96d610
--- /dev/null
+++ b/assets/icons/minus.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/assets/icons/plus.svg b/assets/icons/plus.svg
new file mode 100644
index 00000000..637f5d9f
--- /dev/null
+++ b/assets/icons/plus.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/examples/al-adass2022.html b/examples/al-adass2022.html
index 329ff98d..ad96b808 100644
--- a/examples/al-adass2022.html
+++ b/examples/al-adass2022.html
@@ -10,7 +10,7 @@
import A from '../src/js/A.js';
let aladin;
A.init.then(() => {
- aladin = A.aladin('#aladin-lite-div', {survey: ["P/PanSTARRS/DR1/color-i-r-g"], showReticle: false, gridOptions: {opacity: 0.5, color: 'rgba(255, 0, 0)'}, projection: "AIT", cooFrame: 'galactic', target: "93.2721132 -20.9942421", fov: 1000, showGotoControl: false, showFrame: false, fullScreen: true, showLayersControl: true, showCooGrid: true, showCooGridControl: false});
+ aladin = A.aladin('#aladin-lite-div', {survey: ["P/PanSTARRS/DR1/color-i-r-g"], showReticle: false, gridOptions: {opacity: 0.5, color: 'rgba(255, 0, 0)'}, projection: "AIT", cooFrame: 'icrs', target: "stephan's quintet", fov: 1000, showGotoControl: false, showFrame: false, fullScreen: true, showLayersControl: true, showCooGrid: true, showCooGridControl: false});
const chft = aladin.createImageSurvey('CFHT', "CFHT deep view of NGC7331 and Stephan's quintet u+g+r", "https://cds.unistra.fr/~derriere/PR_HiPS/2022_Duc/", null, null, {imgFormat: 'png'});
const nircamJWST = aladin.createImageSurvey('Nircam', "Stephans Quintet NIRCam+MIRI", "http://alasky.cds.unistra.fr/JWST/CDS_P_JWST_Stephans-Quintet_NIRCam+MIRI/", null, null, {imgFormat: 'png', colormap: "viridis"});
diff --git a/examples/al-easy-access-simbad-ned.html b/examples/al-easy-access-simbad-ned.html
index 0094f95d..6bfdea40 100644
--- a/examples/al-easy-access-simbad-ned.html
+++ b/examples/al-easy-access-simbad-ned.html
@@ -22,12 +22,8 @@
showStatusBar: {
position: {
bottom: 0,
- left: 50
+ left: '7rem'
},
- cssStyle: {
- border: '1px solid white',
- color: 'yellow',
- }
},
showStackLayerControl: true,
samp: true,
diff --git a/src/css/aladin.css b/src/css/aladin.css
index 404c839e..651fb375 100644
--- a/src/css/aladin.css
+++ b/src/css/aladin.css
@@ -317,7 +317,7 @@ word-wrap:break-word;
}
.aladin-box-night {
- padding: '2px';
+ padding: 0.5rem;
background-color: #000;
color: white;
}
@@ -623,15 +623,15 @@ canvas {
}
.aladin-btn.small-sized-icon {
- padding: 0px;
- width: 16px;
- height: 16px;
+ padding: 0;
+ width: 1.5rem;
+ height: 1.5rem;
}
.aladin-btn.medium-sized-icon {
- padding: 0px;
- width: 24px;
- height: 24px;
+ padding: 0;
+ width: 2rem;
+ height: 2rem;
}
.aladin-btn.svg-icon {
@@ -675,17 +675,16 @@ canvas {
.aladin-fov, .aladin-location, .aladin-cooFrame {
font-family: monospace;
-
- border: 1px solid white;
- border-radius: 3px;
+ height: 1.5rem;
background-color: rgba(0, 0, 0, 0.5);
color: white;
+
+ font-size: 1rem;
+ text-shadow: 0px 0px 2px #000;
}
-.aladin-zoom-controls {
-}
.aladin-cancelBtn {
background-color: #ca4242;
@@ -1019,11 +1018,11 @@ canvas {
border-top: 1px solid #d2d2d2;
margin-top: -1px;
}
-
+/*
.aladin-context-menu .aladin-context-menu-item:hover > .aladin-context-sub-menu {
display: block;
}
-
+*/
.aladin-context-menu.left .aladin-context-sub-menu {
left: 0;
transform: translateX(-100%);
@@ -1061,10 +1060,12 @@ canvas {
-moz-appearance: none;
-webkit-appearance: none;
outline-style: none;
- padding: 2px;
+ padding: 0.3rem;
border: none;
border-radius: 5px;
background-color: white;
+ font-family: monospace;
+ font-size: 1rem;
}
.aladin-input-text::placeholder {
@@ -1074,11 +1075,7 @@ canvas {
/* Input select */
.aladin-input-select {
- all:unset;
/* Reset */
- -webkit-appearance: none;
- -moz-appearance: none;
- appearance: none;
border: 1px solid white;
outline: 0;
font: inherit;
diff --git a/src/js/Aladin.js b/src/js/Aladin.js
index c85c4702..78ca785e 100644
--- a/src/js/Aladin.js
+++ b/src/js/Aladin.js
@@ -40,7 +40,8 @@ import { MeasurementTable } from "./MeasurementTable.js";
import { ImageSurvey } from "./ImageSurvey.js";
import { Coo } from "./libs/astro/coo.js";
import { CooConversion } from "./CooConversion.js";
-import { GotoBox } from "./gui/Box/GotoBox.js";
+import plusIconUrl from "../../assets/icons/plus.svg"
+import minusIconUrl from "../../assets/icons/minus.svg"
import { ProjectionEnum } from "./ProjectionEnum.js";
@@ -58,12 +59,12 @@ import { FoV } from "./gui/FoV.js";
import { ShareActionButton } from "./gui/Button/ShareView.js";
import { Menu } from "./gui/Toolbar/Menu.js";
import { ContextMenu } from "./gui/Widgets/ContextMenu.js";
-import { ProjectionActionButton } from "./gui/Button/Projection.js";
import { Input } from "./gui/Widgets/Input.js";
import { Popup } from "./Popup.js";
import A from "./A.js";
import { SnapshotActionButton } from "./gui/Button/Snapshot.js";
import { StatusBarBox } from "./gui/Box/StatusBarBox.js";
+import { FullScreenActionButton } from "./gui/Button/FullScreen.js";
/**
* @typedef {Object} AladinOptions
* @description Options for configuring the Aladin Lite instance.
@@ -371,17 +372,13 @@ export let Aladin = (function () {
viewport.add(new FoV(this))
}
- // Add the projection control
- if (options.showProjectionControl) {
- viewport.add(new ProjectionActionButton(self), 'proj')
- }
-
////////////////////////////////////////////////////
let menu = new Menu({
orientation: 'vertical',
- direction: 'right',
+ direction: 'left',
position: {
- anchor: 'right top'
+ left: '0px',
+ top: '3rem'
}
}, this);
@@ -402,6 +399,10 @@ export let Aladin = (function () {
if (options.showSimbadPointerControl) {
menu.enable('simbad')
}
+ // Add the projection control
+ if (options.showProjectionControl) {
+ menu.enable('projection')
+ }
// Add the goto control
if (options.showGotoControl) {
menu.enable('goto')
@@ -415,10 +416,6 @@ export let Aladin = (function () {
menu.enable('settings')
}
- if (options.showFullscreenControl) {
- menu.enable('fullscreen')
- }
-
this.addUI(viewport);
this.addUI(menu);
@@ -430,6 +427,9 @@ export let Aladin = (function () {
anchor: 'left bottom'
}
}, this);
+ if (options.showFullscreenControl) {
+ share.add(new FullScreenActionButton(self))
+ }
share.add(new ShareActionButton(self))
share.add(new SnapshotActionButton({
tooltip: {
@@ -446,7 +446,7 @@ export let Aladin = (function () {
// zoom control
if (options.showZoomControl) {
let plusZoomBtn = A.button({
- content: '+',
+ iconURL: plusIconUrl,
tooltip: {
content: 'Zoom',
position: {
@@ -460,7 +460,7 @@ export let Aladin = (function () {
plusZoomBtn.addClass('medium-sized-icon')
let minusZoomBtn = A.button({
- content: '-',
+ iconURL: minusIconUrl,
tooltip: {
content: 'Unzoom',
position: {
@@ -527,32 +527,33 @@ export let Aladin = (function () {
var mqSmallSize = window.matchMedia("(max-width: 410px)")
- function mqSmallSizeFunction(x) {
+ /*function mqSmallSizeFunction(x) {
if (x.matches) { // If media query matches
self.menu.update({
- direction: 'left',
+ direction: 'right',
position: {
- top: 23,
- left: 0
+ top: '23px',
+ left: '0px'
}
})
} else {
self.menu.update({
- direction: 'right',
+ direction: 'left',
position: {
- anchor: 'right top'
+ top: '23px',
+ left: '0px'
}
})
}
- }
+ }*/
// Attach listener function on state changes
- mqSmallSize.addEventListener("change", function() {
+ /*mqSmallSize.addEventListener("change", function() {
mqSmallSizeFunction(mqSmallSize);
- });
+ });*/
// Call listener function at run time
- mqSmallSizeFunction(mqSmallSize);
+ //mqSmallSizeFunction(mqSmallSize);
mqMediumSizeFunction(mqMediumSize);
}
@@ -618,6 +619,10 @@ export let Aladin = (function () {
realFullscreen = Boolean(realFullscreen);
self.isInFullscreen = !self.isInFullscreen;
+ if (this.menu) {
+ this.menu.closeAll();
+ }
+
//this.fullScreenBtn.attr('title', isInFullscreen ? 'Restore original size' : 'Full screen');
if (this.aladinDiv.classList.contains('aladin-fullscreen')) {
diff --git a/src/js/Reticle.js b/src/js/Reticle.js
index 9b0ff37b..a01c7bd0 100644
--- a/src/js/Reticle.js
+++ b/src/js/Reticle.js
@@ -17,7 +17,6 @@
// along with Aladin Lite.
//
-import iconUrl from './../../assets/icons/reticle.svg'
import { Color } from './Color.js';
/******************************************************************************
diff --git a/src/js/View.js b/src/js/View.js
index 8a191800..9ed5835b 100644
--- a/src/js/View.js
+++ b/src/js/View.js
@@ -1051,8 +1051,8 @@ export let View = (function () {
a1 = 0.002;
a0 = 0.0002;
} else {
- a1 = 0.0025;
- a0 = 0.0001;
+ a1 = 0.01;
+ a0 = 0.0004;
}
const alpha = Math.pow(view.fov / view.projection.fov, 0.5);
diff --git a/src/js/gui/Box/GotoBox.js b/src/js/gui/Box/GotoBox.js
index 365abb2b..7516b257 100644
--- a/src/js/gui/Box/GotoBox.js
+++ b/src/js/gui/Box/GotoBox.js
@@ -30,6 +30,7 @@
import { Box } from "../Widgets/Box.js";
import { Input } from "../Widgets/Input.js";
+import { Layout } from "../Layout.js";
export class GotoBox extends Box {
// Constructor
@@ -82,7 +83,7 @@ export class GotoBox extends Box {
}
});
- super(aladin, {content: textField})
+ super(aladin, {content: Layout.horizontal(["Target: ", textField])})
this.addClass('aladin-box-night');
this.textField = textField;
diff --git a/src/js/gui/Box/SurveyEditBox.js b/src/js/gui/Box/SurveyEditBox.js
index a7fd5eb2..6ecef798 100644
--- a/src/js/gui/Box/SurveyEditBox.js
+++ b/src/js/gui/Box/SurveyEditBox.js
@@ -50,8 +50,7 @@ import { CmapSelector } from "../Selector/Colormap.js";
cssStyle: {
padding: '4px',
backgroundColor: 'black',
- },
- ...options
+ }
}
)
@@ -61,12 +60,7 @@ import { CmapSelector } from "../Selector/Colormap.js";
this.selector = new SelectorButton({
luminosity: {
iconURL: luminosityIconUrl,
- tooltip: {content: 'Luminosity sliders', position: {direction: 'left'}},
- cssStyle: {
- width: '18px',
- height: '18px',
- padding: 0,
- },
+ tooltip: {content: 'Luminosity sliders', position: {direction: 'right'}},
change(e) {
const content = Layout.horizontal({
layout: [self.selector, self.luminositySettingsContent]
@@ -76,12 +70,7 @@ import { CmapSelector } from "../Selector/Colormap.js";
},
opacity: {
iconURL: opacityIconUrl,
- tooltip: {content: 'Opacity slider', position: {direction: 'left'}},
- cssStyle: {
- width: '18px',
- height: '18px',
- padding: 0,
- },
+ tooltip: {content: 'Opacity slider', position: {direction: 'right'}},
change(e) {
const content = Layout.horizontal({layout: [self.selector, self.opacitySettingsContent]});
self.update({content})
@@ -89,12 +78,7 @@ import { CmapSelector } from "../Selector/Colormap.js";
},
colors: {
iconURL: colorIconUrl,
- tooltip: {content: 'Colormap', position: {direction: 'left'}},
- cssStyle: {
- width: '18px',
- height: '18px',
- padding: 0,
- },
+ tooltip: {content: 'Colormap', position: {direction: 'right'}},
change(e) {
const content = Layout.horizontal({layout: [self.selector, self.colorSettingsContent]});
self.update({content})
@@ -102,12 +86,7 @@ import { CmapSelector } from "../Selector/Colormap.js";
},
pixel: {
iconURL: pixelHistIconUrl,
- tooltip: {content: 'Pixel cutouts', position: {direction: 'left'}},
- cssStyle: {
- width: '18px',
- height: '18px',
- padding: 0,
- },
+ tooltip: {content: 'Pixel cutouts', position: {direction: 'right'}},
change(e) {
const content = Layout.horizontal({layout: [self.selector, self.pixelSettingsContent]});
self.update({content})
@@ -152,8 +131,6 @@ import { CmapSelector } from "../Selector/Colormap.js";
sqrt: {
content: 'sqrt',
cssStyle: {
- height: '18px',
- padding: 0,
color: 'black'
},
change(e) {
@@ -164,10 +141,7 @@ import { CmapSelector } from "../Selector/Colormap.js";
linear: {
content: 'linear',
cssStyle: {
- height: '18px',
- padding: 0,
color: 'black'
-
},
change(e) {
let layer = self.options.layer;
@@ -177,10 +151,7 @@ import { CmapSelector } from "../Selector/Colormap.js";
asinh: {
content: 'asinh',
cssStyle: {
- height: '18px',
- padding: 0,
color: 'black'
-
},
change(e) {
let layer = self.options.layer;
@@ -190,8 +161,6 @@ import { CmapSelector } from "../Selector/Colormap.js";
pow2: {
content: 'pow2',
cssStyle: {
- height: '18px',
- padding: 0,
color: 'black'
},
@@ -203,10 +172,7 @@ import { CmapSelector } from "../Selector/Colormap.js";
log: {
content: 'log',
cssStyle: {
- height: '18px',
- padding: 0,
color: 'black'
-
},
change(e) {
let layer = self.options.layer;
@@ -344,7 +310,7 @@ import { CmapSelector } from "../Selector/Colormap.js";
super.update(options)
}
- _show() {
+ _show(options) {
this._hide();
if (this.selector) {
@@ -359,7 +325,7 @@ import { CmapSelector } from "../Selector/Colormap.js";
this.colorSettingsContent._show();
}
- super._show()
+ super._show(options)
}
_hide() {
@@ -399,9 +365,9 @@ import { CmapSelector } from "../Selector/Colormap.js";
static singleton;
- static getInstance(aladin, options) {
+ static getInstance(aladin) {
if (!LayerEditBox.singleton) {
- LayerEditBox.singleton = new LayerEditBox(aladin, options);
+ LayerEditBox.singleton = new LayerEditBox(aladin);
}
return LayerEditBox.singleton;
diff --git a/src/js/gui/Button/CtxMenuOpener.js b/src/js/gui/Button/CtxMenuOpener.js
index 8aa5e134..5620f681 100644
--- a/src/js/gui/Button/CtxMenuOpener.js
+++ b/src/js/gui/Button/CtxMenuOpener.js
@@ -46,7 +46,7 @@ export class CtxMenuActionButtonOpener extends ActionButton {
constructor(options, aladin) {
let self;
- let ctxMenu = new ContextMenu(aladin, {hideOnClick: false})
+ let ctxMenu = new ContextMenu(aladin, {hideOnClick: true, hideOnResize: true})
super({
...options,
cssStyle: {
@@ -55,13 +55,14 @@ export class CtxMenuActionButtonOpener extends ActionButton {
...options.cssStyle
},
action(e) {
- if (options.action) {
- options.action(e)
- }
- self.ctxMenu._hide();
+ //self.ctxMenu._hide();
+
+ if (self.ctxMenu.isHidden === true) {
+ if (options.action) {
+ options.action(e)
+ }
- if (self.hidden === true) {
self.ctxMenu.attach(self.layout)
self.ctxMenu.show({
position: {
@@ -72,13 +73,15 @@ export class CtxMenuActionButtonOpener extends ActionButton {
});
//CtxMenuActionButtonOpener.BUTTONS.forEach(b => {b.hidden = true})
+ } else {
+ self.hideMenu();
}
- self.hidden = !self.hidden;
+ //self.hidden = !self.hidden;
}
})
- this.hidden = true;
+ //this.hidden = true;
this.layout = options.ctxMenu;
@@ -90,7 +93,6 @@ export class CtxMenuActionButtonOpener extends ActionButton {
hideMenu() {
this.ctxMenu._hide();
- this.hidden = true;
}
_hide() {
@@ -105,7 +107,7 @@ export class CtxMenuActionButtonOpener extends ActionButton {
super.update(options)
- if (!this.hidden) {
+ if (!this.ctxMenu.isHidden) {
this.ctxMenu.attach(this.layout)
this.ctxMenu.show({
position: {
diff --git a/src/js/gui/Button/FullScreen.js b/src/js/gui/Button/FullScreen.js
new file mode 100644
index 00000000..1e6e2d48
--- /dev/null
+++ b/src/js/gui/Button/FullScreen.js
@@ -0,0 +1,88 @@
+// 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/Menu.js
+ *
+ *
+ * Author: Matthieu Baumann [CDS, matthieu.baumann@astro.unistra.fr]
+ *
+ *****************************************************************************/
+
+import { ActionButton } from "../Widgets/ActionButton.js";
+
+import restoreIcon from './../../../../assets/icons/restore.svg';
+import maximizeIcon from './../../../../assets/icons/maximize.svg';
+
+export class FullScreenActionButton extends ActionButton {
+ // Constructor
+ constructor(aladin, options) {
+ let self;
+ super({
+ iconURL: aladin.isInFullscreen ? restoreIcon : maximizeIcon,
+ ...options,
+ tooltip: {
+ content: aladin.isInFullscreen ? 'Restore original size' : 'Full-screen',
+ position: {
+ direction: 'top'
+ }
+ },
+ action(e) {
+ if (aladin.statusBar) {
+ aladin.statusBar.removeMessage('tooltip')
+ }
+
+ aladin.toggleFullscreen(aladin.options.realFullscreen);
+
+ if (aladin.isInFullscreen) {
+ // make that div above other aladin lite divs (if there are...)
+ aladin.aladinDiv.style.zIndex = 1
+ self.update({
+ iconURL: restoreIcon,
+ tooltip: {
+ content: 'Restore original size',
+ position: {
+ direction: 'top'
+ }
+ }
+ });
+ } else {
+ aladin.aladinDiv.style.removeProperty('z-index')
+
+ self.update({
+ iconURL: maximizeIcon,
+ tooltip: {
+ content: 'Fullscreen',
+ position: {
+ direction: 'top'
+ }
+ }
+ });
+ }
+ }
+ })
+
+ self = this;
+
+ this.addClass('medium-sized-icon')
+ }
+}
\ No newline at end of file
diff --git a/src/js/gui/Button/GridEnabler.js b/src/js/gui/Button/GridEnabler.js
new file mode 100644
index 00000000..0594457f
--- /dev/null
+++ b/src/js/gui/Button/GridEnabler.js
@@ -0,0 +1,61 @@
+// 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/Menu.js
+ *
+ *
+ * Author: Matthieu Baumann [CDS, matthieu.baumann@astro.unistra.fr]
+ *
+ *****************************************************************************/
+
+import { ActionButton } from "../Widgets/ActionButton.js";
+import gridIcon from './../../../../assets/icons/grid.svg';
+
+export class GridEnabler extends ActionButton {
+ // Constructor
+ constructor(aladin, options) {
+ const computeTooltip = (enabled) => {
+ const content = enabled ? 'Hide the coordinate grid' : 'Display the coordinate grid'
+ return {
+ content,
+ position: {
+ direction: 'top'
+ }
+ }
+ }
+
+ let self;
+ super({
+ iconURL: gridIcon,
+ tooltip: computeTooltip(aladin.getGridOptions().enabled),
+ action(o) {
+ let gridEnabled = aladin.getGridOptions().enabled;
+ aladin.setCooGrid({enabled: !gridEnabled})
+
+ self.update({tooltip: computeTooltip(!gridEnabled)})
+ }
+ })
+ self = this;
+ this.addClass('medium-sized-icon')
+ }
+}
\ No newline at end of file
diff --git a/src/js/gui/Button/Projection.js b/src/js/gui/Button/Projection.js
index 66a7dfad..0619e1e3 100644
--- a/src/js/gui/Button/Projection.js
+++ b/src/js/gui/Button/Projection.js
@@ -40,20 +40,17 @@ import { ProjectionEnum } from "../../ProjectionEnum";
* UI responsible for displaying the viewport infos
* @param {Aladin} aladin - The aladin instance.
*/
- constructor(aladin) {
+ constructor(aladin, options) {
//let ctxMenu = ;
super({
iconURL: projectionSvg,
- tooltip: {content: 'Change the view projection', position: {direction: 'bottom'}},
+ tooltip: {content: 'Change the view projection', position: {direction: 'top'}},
cssStyle: {
backgroundColor: '#bababa',
borderColor: '#484848',
cursor: 'pointer',
},
- openDirection: 'bottom',
- /*action(o) {
- ctxMenu.attach(layout);
- }*/
+ ...options
}, aladin);
let ctxMenu = this._buildLayout(aladin);
diff --git a/src/js/gui/Button/SAMP.js b/src/js/gui/Button/SAMP.js
index a322efee..9833dee4 100644
--- a/src/js/gui/Button/SAMP.js
+++ b/src/js/gui/Button/SAMP.js
@@ -46,13 +46,14 @@ options = {
constructor(options, aladin) {
if (!aladin.samp) {
options = {
+ ...options,
iconURL: waveOffIconUrl,
- tooltip: {content: 'SAMP disabled in Aladin Lite options', position: {direction: 'left'}},
+ tooltip: {content: 'SAMP disabled in Aladin Lite options', position: {direction: 'top'}},
disable: true,
}
} else {
let isHubRunning = aladin.samp.isHubCurrentlyRunning();
- let tooltip = options && options.tooltip || {content: isHubRunning ? 'Connect to SAMP Hub' : 'No hub running found', position: {direction: 'left'}}
+ let tooltip = options && options.tooltip || {content: isHubRunning ? 'Connect to SAMP Hub' : 'No hub running found', position: {direction: 'top'}}
let action = options && options.action
if (!action) {
// default action, just connect and ping
@@ -63,6 +64,7 @@ options = {
let disable = !isHubRunning;
options = {
+ ...options,
iconURL: aladin.samp.isConnected() ? waveOnIconUrl : waveOffIconUrl,
tooltip,
disable,
@@ -74,7 +76,6 @@ options = {
super(options)
- this.addClass('medium-sized-icon')
this._addListeners(aladin);
}
diff --git a/src/js/gui/Button/SimbadPointer.js b/src/js/gui/Button/SimbadPointer.js
index 71c1902a..58b0b814 100644
--- a/src/js/gui/Button/SimbadPointer.js
+++ b/src/js/gui/Button/SimbadPointer.js
@@ -37,25 +37,15 @@
constructor(aladin) {
super({
iconURL: targetIcon,
+ size: 'medium',
tooltip: {
- content: 'What to know what is a specific object ?
Use the Simbad pointer tool!',
- position: { direction: 'left' },
+ content: 'Want to know what is a specific object ?
Use the Simbad pointer tool!',
+ position: { direction: 'right' },
},
- /*cssStyle: {
- padding: 0,
- backgroundColor: '#bababa',
- backgroundPosition: 'center',
- borderColor: '#484848',
- cursor: 'pointer',
- width: '28px',
- height: '28px'
- },*/
action(o) {
aladin.fire('simbad');
}
})
-
- this.addClass('medium-sized-icon')
}
}
\ No newline at end of file
diff --git a/src/js/gui/CtxMenu/GridSettings.js b/src/js/gui/CtxMenu/GridSettings.js
new file mode 100644
index 00000000..eaa1fd83
--- /dev/null
+++ b/src/js/gui/CtxMenu/GridSettings.js
@@ -0,0 +1,178 @@
+// Copyright 2023 - 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 GridSettingsCtxMenu
+ *
+ * Author: Matthieu Baumann [CDS]
+ *
+ *****************************************************************************/
+
+import { ALEvent } from "../../events/ALEvent.js";
+import { Input } from "../Widgets/Input.js";
+import { ActionButton } from "../Widgets/ActionButton.js";
+import { Layout } from "../Layout.js";
+import { Color } from "../../Color.js";
+import thicknessLineIcon from './../../../../assets/icons/thickness.svg';
+import labelSizeIcon from './../../../../assets/icons/font-size.svg';
+
+export let GridSettingsCtxMenu = (function () {
+
+ let GridSettingsCtxMenu = {};
+
+ GridSettingsCtxMenu.getLayout = function (aladin) {
+ let colorInput = new Input({
+ layout: {
+ name: 'gridColor',
+ type: 'color',
+ value: (() => {
+ let c = aladin.getGridOptions().color;
+ const cHex = Color.rgbToHex(c.r * 255, c.g * 255, c.b * 255)
+ return cHex;
+ })(),
+ change(e) {
+ aladin.setCooGrid({color: e.target.value})
+ }
+ }
+ });
+ colorInput.addClass("aladin-input-color");
+
+ let opacitySlider = Input.slider({
+ name: 'opacity',
+ type: 'range',
+ min: 0.0,
+ max: 1.0,
+ value: aladin.getGridOptions().opacity,
+ change(e) {
+ aladin.setCooGrid({opacity: +e.target.value})
+ }
+ });
+
+ const labelSizeSlider = Input.slider({
+ name: 'labelSize',
+ type: 'range',
+ tooltip: {
+ content: 'size'
+ },
+ min: 0.0,
+ max: 1.0,
+ value: 0.5,
+ change(e) {
+ aladin.setCooGrid({labelSize: Math.round(+e.target.value * 20)})
+ }
+ });
+
+ const thicknessLineBtn = ActionButton.createSmallSizedIconBtn({
+ iconURL: thicknessLineIcon,
+ tooltip: {content: 'Grid line thickness', position: {direction: 'left'}},
+ cssStyle: {
+ backgroundColor: '#bababa',
+ borderColor: '#484848',
+ cursor: 'pointer',
+ width: '20px',
+ height: '20px',
+ padding: '0',
+ },
+ action(e) {
+ let ctxMenu = ContextMenu.getInstance(aladin);
+ ctxMenu._hide();
+
+ let ctxMenuLayout = [];
+ for (let thickness = 1; thickness <= 5; thickness++) {
+ ctxMenuLayout.push({
+ label: thickness + 'px',
+ action(o) {
+ aladin.setCooGrid({thickness: thickness})
+ }
+ })
+ }
+
+ ctxMenu.attach(ctxMenuLayout);
+ ctxMenu.show({
+ e: e,
+ position: {
+ nextTo: thicknessLineBtn,
+ direction: 'bottom',
+ }
+ })
+ }
+ });
+
+ let enableCheckbox = Input.checkbox({
+ name: 'enableGrid',
+ tooltip: {content: 'Enable/disable the grid', position: {direction: 'left'}},
+ type: 'checkbox',
+ checked: aladin.getGridOptions().enabled,
+ click(e) {
+ aladin.setCooGrid({enabled: enableCheckbox.get()})
+ }
+ });
+
+ ALEvent.COO_GRID_UPDATED.listenedBy(aladin.aladinDiv, function (e) {
+ let color = e.detail.color;
+
+ let hexColor = Color.rgbToHex(Math.round(255 * color.r), Math.round(255 * color.g), Math.round(255 * color.b));
+ colorInput.set(hexColor)
+ });
+
+ return {
+ label: 'Grid',
+ subMenu: [{
+ label: {
+ content: ['Show/Hide']
+ },
+ action(o) {
+ /*let newVal = toggleCheckbox(gridCheckbox);
+ aladin.showReticle(newVal)
+
+ self._attach();*/
+ }
+ },
+ {
+ label: {
+ content: ['Color ', colorInput],
+ },
+ mustHide: false,
+ action(o) {}
+ },
+ {
+ label: {
+ content: ['Opacity ', opacitySlider],
+ },
+ mustHide: false,
+ action(o) {}
+ },
+ {
+ label: {
+ content: ['Label', labelSizeSlider]
+ },
+ mustHide: false,
+ action(o) {}
+ }
+ ]
+ }
+ }
+
+ return GridSettingsCtxMenu;
+
+})();
diff --git a/src/js/gui/CtxMenu/OverlayStack.js b/src/js/gui/CtxMenu/OverlayStack.js
index 5d4c26fe..c6582d2e 100644
--- a/src/js/gui/CtxMenu/OverlayStack.js
+++ b/src/js/gui/CtxMenu/OverlayStack.js
@@ -40,21 +40,24 @@ import A from "../../A.js";
import { Utils } from "../../../js/Utils";
export class OverlayStack extends ContextMenu {
+
+ static predefinedCats = {
+ simbad: {url: 'https://axel.u-strasbg.fr/HiPSCatService/SIMBAD', options: {id: 'simbad', name: 'SIMBAD', shape: 'circle', sourceSize: 8, color: '#318d80'}},
+ gaia: {url: 'https://axel.u-strasbg.fr/HiPSCatService/I/355/gaiadr3', options: {id: 'gaia-dr3', name: 'Gaia DR3', shape: 'square', sourceSize: 8, color: '#6baed6'}},
+ twomass: {url: 'https://axel.u-strasbg.fr/HiPSCatService/II/246/out', options: {id: '2mass', name: '2MASS', shape: 'plus', sourceSize: 8, color: '#dd2233'}}
+ };
// Constructor
constructor(aladin) {
- super(aladin, {hideOnClick: false});
+ let self;
+ super(aladin, {hideOnClick: (e) => {
+ if (self.mode === 'stack') {
+ self._hide();
+ }
+ }});
+ self = this;
this.aladin = aladin;
- //this.anchor = menu.controls["OverlayStack"];
this.mode = 'stack';
- /*window.addEventListener("resize", (e) => {
- this._hide();
- })*/
- /*document.addEventListener('click', (e) => {
- if (!self.el.contains(e.target) && this.mode === 'stack') {
- this._hide()
- }
- });*/
this._addListeners();
}
@@ -98,8 +101,50 @@ export class OverlayStack extends ContextMenu {
{
label: 'Catalogue',
subMenu: [
+ {
+ label: 'Simbad',
+ action(o) {
+ o.stopPropagation();
+ o.preventDefault();
+
+ self._hide();
+
+ const simbadHiPS = A.catalogHiPS(OverlayStack.predefinedCats.simbad.url, OverlayStack.predefinedCats.simbad.options);
+ self.aladin.addCatalog(simbadHiPS);
+
+ self.mode = 'stack';
+ }
+ },
+ {
+ label: 'Gaia DR3',
+ action(o) {
+ o.stopPropagation();
+ o.preventDefault();
+
+ self._hide();
+
+ const simbadHiPS = A.catalogHiPS(OverlayStack.predefinedCats.gaia.url, OverlayStack.predefinedCats.gaia.options);
+ self.aladin.addCatalog(simbadHiPS);
+
+ self.mode = 'stack';
+ }
+ },
+ {
+ label: '2MASS',
+ action(o) {
+ o.stopPropagation();
+ o.preventDefault();
+
+ self._hide();
+
+ const simbadHiPS = A.catalogHiPS(OverlayStack.predefinedCats.twomass.url, OverlayStack.predefinedCats.twomass.options);
+ self.aladin.addCatalog(simbadHiPS);
+
+ self.mode = 'stack';
+ }
+ },
ContextMenu.fileLoaderItem({
- label: 'VOTable File',
+ label: 'From a VOTable File',
accept: '.xml,.vot',
action(file) {
let url = URL.createObjectURL(file);
@@ -115,19 +160,19 @@ export class OverlayStack extends ContextMenu {
}
}),
{
- label: 'Find in our databases...',
+ label: 'More...',
action(o) {
- //o.stopPropagation();
- //o.preventDefault();
+ o.stopPropagation();
+ o.preventDefault();
self._hide();
- self.catBox = CatalogQueryBox.getInstance(self.aladin);
- console.log(self.position)
- self.catBox._show({position: self.position});
+
+ let catBox = CatalogQueryBox.getInstance(self.aladin);
+ catBox._show({position: self.position});
self.mode = 'search';
}
- }
+ },
]
},
{
@@ -152,6 +197,9 @@ export class OverlayStack extends ContextMenu {
{
label: 'Circle',
action(o) {
+ o.preventDefault();
+ o.stopPropagation();
+
self._hide();
self.aladin.select('circle', c => {
@@ -173,6 +221,9 @@ export class OverlayStack extends ContextMenu {
{
label: 'Rect',
action(o) {
+ o.stopPropagation();
+ o.preventDefault();
+
self._hide();
self.aladin.select('rect', r => {
@@ -199,6 +250,9 @@ export class OverlayStack extends ContextMenu {
{
label: 'Polygon',
action(o) {
+ o.stopPropagation();
+ o.preventDefault();
+
self._hide();
self.aladin.select('poly', p => {
@@ -235,15 +289,14 @@ export class OverlayStack extends ContextMenu {
let cssStyle = {
height: 'fit-content',
};
- let showBtn = ActionButton.createIconBtn({
+ let showBtn = new ActionButton({
+ size: 'small',
iconURL: overlay.isShowing ? showIconUrl : hideIconUrl,
cssStyle: {
backgroundColor: '#bababa',
borderColor: '#484848',
color: 'black',
visibility: Utils.hasTouchScreen() ? 'visible' : 'hidden',
- width: '18px',
- height: '18px',
verticalAlign: 'middle',
marginRight: '2px',
},
@@ -259,20 +312,19 @@ export class OverlayStack extends ContextMenu {
}
});
- let deleteBtn = ActionButton.createIconBtn({
+ let deleteBtn = new ActionButton({
iconURL: removeIconUrl,
+ size: 'small',
cssStyle: {
backgroundColor: '#bababa',
borderColor: '#484848',
color: 'black',
visibility: Utils.hasTouchScreen() ? 'visible' : 'hidden',
- width: '18px',
- height: '18px',
verticalAlign: 'middle'
},
tooltip: {
content: 'Remove',
- position: {direction: 'left'}
+ position: {direction: 'bottom'}
},
action(e) {
self.aladin.removeLayer(overlay)
@@ -332,13 +384,22 @@ export class OverlayStack extends ContextMenu {
iconSvg = AladinUtils.SVG_ICONS.OVERLAY;
}
+ let changeSVGSize = (svg, size) => {
+ let str = svg.replace(/FILLCOLOR/g, 'black')
+ let elt = document.createElement('div');
+ elt.innerHTML = str;
+
+ elt.querySelector('svg').setAttribute('width', size);
+ elt.querySelector('svg').setAttribute('height', size);
+
+ return elt.innerHTML;
+ };
// retrieve SVG icon, and apply the layer color
- var svgBase64 = window.btoa(iconSvg.replace(/FILLCOLOR/g, overlay.color));
- let icon = ActionButton.createIconBtn({
- tooltip: {content: tooltipText, position: {direction: 'left'}},
+ var svgBase64 = window.btoa(changeSVGSize(iconSvg.replace(/FILLCOLOR/g, overlay.color), '1rem'));
+ let icon = new ActionButton({
+ size: 'small',
+ tooltip: {content: tooltipText, position: {direction: 'bottom'}},
cssStyle: {
- width: '16px',
- height: '16px',
backgroundImage: 'url("data:image/svg+xml;base64,' + svgBase64 + '")',
}
});
@@ -364,17 +425,9 @@ export class OverlayStack extends ContextMenu {
_hide() {
this.mode = 'stack';
-
- if (this.catBox) {
- this.catBox._hide();
- }
- /*let catBox = CatalogQueryBox.getInstance(this.aladin, this.position);
-
-
- if (this.position) {
-
- }*/
+ let catBox = CatalogQueryBox.getInstance(this.aladin);
+ catBox._hide();
super._hide();
}
diff --git a/src/js/gui/CtxMenu/Settings.js b/src/js/gui/CtxMenu/Settings.js
index fab4e232..55b2a775 100644
--- a/src/js/gui/CtxMenu/Settings.js
+++ b/src/js/gui/CtxMenu/Settings.js
@@ -36,11 +36,12 @@ import { ALEvent } from "../../events/ALEvent.js";
import { SAMPActionButton } from "../Button/SAMP.js";
import helpIconBtn from '../../../../assets/icons/help.svg';
import { Utils } from "../../Utils";
+import { GridSettingsCtxMenu } from "./GridSettings.js";
export class SettingsCtxMenu extends ContextMenu {
// Constructor
constructor(aladin, menu) {
- super(aladin);
+ super(aladin, {hideOnClick: true});
let self = this;
self.backgroundColorInput = Input.color({
name: 'color',
@@ -106,6 +107,7 @@ export class SettingsCtxMenu extends ContextMenu {
this.menu = menu;
let sampBtn = new SAMPActionButton({
+ size: 'small',
action(conn) {
if (conn.isConnected()) {
conn.unregister();
@@ -186,6 +188,7 @@ export class SettingsCtxMenu extends ContextMenu {
}
]
},
+ GridSettingsCtxMenu.getLayout(self.aladin),
{
label: {
content: [self.hpxGridCheckbox, 'HEALPix grid']
@@ -234,21 +237,15 @@ export class SettingsCtxMenu extends ContextMenu {
action(o) {
toggleWindow('grid');
}
- },
- {
- label: 'FullScreen',
- selected: self.menu.isShown('fullscreen'),
- action(o) {
- toggleWindow('fullscreen');
- }
}
]
},
{
label: {
icon: {
- tooltip: {content: 'Documentation about Aladin Lite', position: {direction: 'left'}},
+ tooltip: {content: 'Documentation about Aladin Lite', position: {direction: 'top'}},
iconURL: helpIconBtn,
+ size: 'small',
cssStyle: {
cursor: 'help',
}
diff --git a/src/js/gui/CtxMenu/SurveyStack.js b/src/js/gui/CtxMenu/SurveyStack.js
index 6dc15416..49b8123f 100644
--- a/src/js/gui/CtxMenu/SurveyStack.js
+++ b/src/js/gui/CtxMenu/SurveyStack.js
@@ -50,10 +50,8 @@ import A from '../../A';
export class Stack extends ContextMenu {
static previewImagesUrl = {
'AllWISE color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_allWISE_color.jpg',
- 'DECaPS DR1 color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_DECaLS_DR5_color.jpg',
'DSS colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_DSS2_color.jpg',
'DSS2 Red (F+R)': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_DSS2_red.jpg',
- 'Density map for Gaia EDR3 (I/350/gaiaedr3)' : undefined,
'Fermi color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_Fermi_color.jpg',
'GALEXGR6_7 NUV': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_GALEXGR6_7_color.jpg',
'GLIMPSE360': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_GLIMPSE360.jpg',
@@ -62,7 +60,6 @@ export class Stack extends ContextMenu {
'IRIS colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_IRIS_color.jpg',
'Mellinger colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_Mellinger_color.jpg',
'PanSTARRS DR1 color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_PanSTARRS_DR1_color-z-zg-g.jpg',
- 'PanSTARRS DR1 g': undefined,
'2MASS colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_2MASS_color.jpg',
'AKARI colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_AKARI_FIS_Color.jpg',
'SWIFT': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_SWIFT_BAT_FLUX.jpg',
@@ -73,7 +70,13 @@ export class Stack extends ContextMenu {
// Constructor
constructor(aladin) {
- super(aladin, {hideOnClick: false});
+ let self;
+ super(aladin, {hideOnClick: (e) => {
+ if (self.mode === 'stack') {
+ self._hide();
+ }
+ }});
+ self = this;
this.aladin = aladin;
//this.anchor = menu.controls["Stack"];
//this.fsm = new StackLayerOpenerFSM(aladin, menu);
@@ -145,19 +148,17 @@ export class Stack extends ContextMenu {
cursor: 'help',
},
},
- content: 'Search a survey'
+ content: 'Search for a survey'
},
- action(e) {
- /*if (e) {
- e.stopPropagation();
- e.preventDefault();
- }*/
+ action: (e) => {
+ e.stopPropagation();
+ e.preventDefault();
self._hide();
- self.hipsSelectorBox = HiPSSelectorBox.getInstance(self.aladin);
+ let hipsSelectorBox = HiPSSelectorBox.getInstance(self.aladin);
// attach a callback
- self.hipsSelectorBox.attach(
+ hipsSelectorBox.attach(
(HiPSId) => {
let name = Utils.uuidv4()
self.aladin.setOverlayImageLayer(HiPSId, name)
@@ -167,7 +168,7 @@ export class Stack extends ContextMenu {
}
);
- self.hipsSelectorBox._show({
+ hipsSelectorBox._show({
position: self.position,
});
@@ -217,7 +218,7 @@ export class Stack extends ContextMenu {
for(const layer of layers) {
const name = layer.name;
- let backgroundUrl = this._findPreviewImageUrl(layer);
+ let backgroundUrl = layer.properties.url + '/preview.jpg';
let cssStyle = {
height: 'fit-content',
};
@@ -230,15 +231,13 @@ export class Stack extends ContextMenu {
}
}
- let showBtn = ActionButton.createIconBtn({
+ let showBtn = ActionButton.createSmallSizedIconBtn({
iconURL: layer.getOpacity() === 0.0 ? hideIconUrl : showIconUrl,
cssStyle: {
backgroundColor: '#bababa',
borderColor: '#484848',
color: 'black',
visibility: Utils.hasTouchScreen() ? 'visible' : 'hidden',
- width: '18px',
- height: '18px',
verticalAlign: 'middle',
marginRight: '2px',
},
@@ -258,32 +257,29 @@ export class Stack extends ContextMenu {
}
});
- let deleteBtn = ActionButton.createIconBtn({
+ let deleteBtn = ActionButton.createSmallSizedIconBtn({
iconURL: removeIconUrl,
cssStyle: {
backgroundColor: '#bababa',
borderColor: '#484848',
color: 'black',
visibility: Utils.hasTouchScreen() ? 'visible' : 'hidden',
- width: '18px',
- height: '18px',
verticalAlign: 'middle'
},
disable: layer.layer === 'base',
- tooltip: {content: 'Remove', position: {direction: 'left'}},
+ tooltip: {content: 'Remove', position: {direction: 'bottom'}},
action(e) {
self.aladin.removeImageLayer(layer.layer);
}
});
- let editBtn = ActionButton.createIconBtn({
+
+ let editBtn = ActionButton.createSmallSizedIconBtn({
iconURL: editIconUrl,
cssStyle: {
backgroundColor: '#bababa',
borderColor: '#484848',
color: 'black',
visibility: Utils.hasTouchScreen() ? 'visible' : 'hidden',
- width: '18px',
- height: '18px',
verticalAlign: 'middle',
marginRight: '2px',
},
@@ -297,27 +293,37 @@ export class Stack extends ContextMenu {
self.aladin.selectLayer(layer.layer);
self.attach({layers})
- let editBox = LayerEditBox.getInstance(self.aladin, {position: self.position});
+ let editBox = LayerEditBox.getInstance(self.aladin);
editBox.update({layer})
- editBox._show();
+ editBox._show({position: self.position});
self.mode = 'edit';
}
});
- let loadMOCBtn = ActionButton.createIconBtn({
+ let changeSVGSize = (svg, size) => {
+ let str = svg.replace(/FILLCOLOR/g, 'black')
+ let elt = document.createElement('div');
+ elt.innerHTML = str;
+
+ elt.querySelector('svg').setAttribute('width', size);
+ elt.querySelector('svg').setAttribute('height', size);
+
+ return elt.innerHTML;
+ };
+
+ let loadMOCBtn = new ActionButton({
+ size: 'small',
cssStyle: {
backgroundColor: '#bababa',
borderColor: '#484848',
color: 'black',
visibility: Utils.hasTouchScreen() ? 'visible' : 'hidden',
- backgroundImage: 'url("data:image/svg+xml;base64,' + window.btoa(AladinUtils.SVG_ICONS.MOC.replace(/FILLCOLOR/g, 'black')) + '")',
- width: '16px',
- height: '18px',
+ backgroundImage: 'url("data:image/svg+xml;base64,' + window.btoa(changeSVGSize(AladinUtils.SVG_ICONS.MOC.replace(/FILLCOLOR/g, 'black'), '1rem')) + '")',
verticalAlign: 'middle',
marginRight: '2px',
},
- tooltip: {content: 'Add coverage', position: {direction: 'left'}},
+ tooltip: {content: 'Add coverage', position: {direction: 'bottom'}},
action: (e) => {
let moc = A.MOCFromURL(layer.properties.url + '/Moc.fits', {lineWidth: 3, name: layer.properties.obsTitle});
self.aladin.addMOC(moc);
@@ -333,7 +339,6 @@ export class Stack extends ContextMenu {
});
loadMOCBtn.addClass('svg-icon')
-
let layerClassName = 'a' + layer.layer.replace(/[.\/ ]/g, '')
let btns = [showBtn, editBtn];
@@ -375,43 +380,13 @@ export class Stack extends ContextMenu {
};
//if (layer.layer === "base") {
- l.subMenu = [{
- label: {
- icon: {
- iconURL: searchIconImg,
- tooltip: {content: 'Find a specific survey
in our database...', position: { direction: 'bottom' }},
- cssStyle: {
- backgroundPosition: 'center center',
- backgroundColor: '#bababa',
- border: '1px solid rgb(72, 72, 72)',
- cursor: 'help',
- },
- },
- content: 'Search for a new survey'
- },
- action(o) {
- self._hide();
-
- self.hipsBox = HiPSSelectorBox.getInstance(self.aladin)
-
- self.hipsBox.attach(
- (HiPSId) => {
- self.aladin.setOverlayImageLayer(HiPSId, layer.layer);
- self.mode = 'stack';
- self._show();
- }
- );
-
- self.hipsBox._show({
- position: self.position,
- })
-
- self.mode = 'hips';
- }
- }];
+ l.subMenu = [];
for(let ll of defaultLayers) {
- let backgroundUrl = Stack.previewImagesUrl[ll.name];
+ backgroundUrl = Stack.previewImagesUrl[ll.name];
+ if (!backgroundUrl) {
+ backgroundUrl = ll.url + '/preview.jpg'
+ }
let cssStyle = {
height: '2.5em',
};
@@ -462,6 +437,44 @@ export class Stack extends ContextMenu {
}
})
}
+
+ l.subMenu.push({
+ label: {
+ icon: {
+ iconURL: searchIconImg,
+ tooltip: {content: 'Find a specific survey
in our database...', position: { direction: 'top' }},
+ cssStyle: {
+ backgroundPosition: 'center center',
+ backgroundColor: '#bababa',
+ border: '1px solid rgb(72, 72, 72)',
+ cursor: 'help',
+ },
+ },
+ content: 'More...'
+ },
+ action(o) {
+ o.stopPropagation();
+ o.preventDefault();
+
+ self._hide();
+
+ let hipsBox = HiPSSelectorBox.getInstance(self.aladin)
+
+ hipsBox.attach(
+ (HiPSId) => {
+ self.aladin.setOverlayImageLayer(HiPSId, layer.layer);
+ self.mode = 'stack';
+ self._show();
+ }
+ );
+
+ hipsBox._show({
+ position: self.position,
+ })
+
+ self.mode = 'hips';
+ }
+ })
//}
l.action = (o) => {
@@ -493,6 +506,8 @@ export class Stack extends ContextMenu {
return Stack.previewImagesUrl[key];
}
}
+ // if not found
+ return layer.properties.url + '/preview.jpg'
}
_show(options) {
@@ -501,7 +516,7 @@ export class Stack extends ContextMenu {
super.show({
position: this.position,
cssStyle: {
- maxWidth: '15em',
+ maxWidth: '15rem',
backgroundColor: 'black',
}
})
@@ -520,14 +535,13 @@ export class Stack extends ContextMenu {
_hide() {
// go back to the display stack state
- if (this.position) {
- let editBox = LayerEditBox.getInstance(this.aladin, {position: this.position});
+ //if (this.mode === 'stack') {
+ let editBox = LayerEditBox.getInstance(this.aladin);
editBox._hide();
- }
- if (this.hipsSelectorBox) {
- this.hipsSelectorBox._hide();
- }
+ let hipsSelectorBox = HiPSSelectorBox.getInstance(this.aladin);
+ hipsSelectorBox._hide();
+ //}
this.mode = 'stack';
diff --git a/src/js/gui/FoV.js b/src/js/gui/FoV.js
index a568de8e..78577e3d 100644
--- a/src/js/gui/FoV.js
+++ b/src/js/gui/FoV.js
@@ -49,11 +49,6 @@ export class FoV extends DOMElement {
super(el)
- if (Utils.hasTouchScreen()) {
- // Add a little padding
- this.el.style.padding = "0.5em";
- }
-
let self = this;
ALEvent.ZOOM_CHANGED.listenedBy(aladin.aladinDiv, function (e) {
let [fovXDeg, fovYDeg] = aladin.getFov();
diff --git a/src/js/gui/Location.js b/src/js/gui/Location.js
index 1e4087f1..cd2b69f2 100644
--- a/src/js/gui/Location.js
+++ b/src/js/gui/Location.js
@@ -47,12 +47,8 @@ export class Location extends DOMElement {
let el = Layout.horizontal({
layout: [
- ActionButton.createIconBtn({
+ ActionButton.createSmallSizedIconBtn({
iconURL: copyIconBtn,
- cssStyle: {
- width: '16px',
- height: '16px',
- },
tooltip: {content: 'Copy to clipboard!', position: {direction: 'bottom'}},
action(e) {
self.copyCoordinatesToClipboard()
@@ -118,10 +114,6 @@ export class Location extends DOMElement {
isViewCenter: true,
frame: aladin.view.cooFrame
}, aladin)
-
- if (Utils.hasTouchScreen()) {
- this.el.style.padding = "0.2em";
- }
};
static prec = 7;
diff --git a/src/js/gui/Selector/Colormap.js b/src/js/gui/Selector/Colormap.js
index e3440c81..85c3fa57 100644
--- a/src/js/gui/Selector/Colormap.js
+++ b/src/js/gui/Selector/Colormap.js
@@ -60,13 +60,12 @@ export class CmapSelector extends SelectorButton {
options[cmap] = {
...options[cmap],
cssStyle: {
- padding: '0px',
//border: 'none',
//borderRadius: '0',
//backgroundColor: 'black',
color: 'black',
+ width: '4rem',
overflow: 'hidden',
- width: '6em',
'font-family': 'monospace',
},
content: cmap,
diff --git a/src/js/gui/Toolbar/Menu.js b/src/js/gui/Toolbar/Menu.js
index 41f7e236..2135a851 100644
--- a/src/js/gui/Toolbar/Menu.js
+++ b/src/js/gui/Toolbar/Menu.js
@@ -26,15 +26,13 @@ import { Stack } from "../CtxMenu/SurveyStack";
import { OverlayStack } from "../CtxMenu/OverlayStack";
import { GotoBox } from "../Box/GotoBox";
import { SimbadPointer } from "../Button/SimbadPointer";
-import { GridBox } from "../Box/GridBox";
+import { ProjectionActionButton } from "../Button/Projection";
import settingsIcon from './../../../../assets/icons/settings.svg';
import stackOverlayIconUrl from './../../../../assets/icons/stack.svg';
import stackImageIconUrl from './../../../../assets/icons/telescope.svg';
-import gridIcon from './../../../../assets/icons/grid.svg';
+import { GridEnabler } from '../Button/GridEnabler';
import searchIcon from './../../../../assets/icons/search.svg';
-import restoreIcon from './../../../../assets/icons/restore.svg';
-import maximizeIcon from './../../../../assets/icons/maximize.svg';
import { Utils as UtilsExt } from "../../Utils";
import { Utils } from "../Utils";
@@ -82,20 +80,14 @@ import { Toolbar } from "../Widgets/Toolbar";
})
}
- UtilsExt.on(aladin.aladinDiv, 'dblclick', () => {
- self.closeAll();
- });
-
- // Add the fullscreen control
// tools
let stack = new Stack(aladin, self);
let overlay = new OverlayStack(aladin);
let goto = new GotoBox(aladin);
- let grid = new GridBox(aladin);
let settings = new SettingsCtxMenu(aladin, self);
this.panels = {
- stack, overlay, goto, grid, settings
+ stack, overlay, goto, settings
};
this.indices = [];
@@ -113,8 +105,9 @@ import { Toolbar } from "../Widgets/Toolbar";
iconURL: stackImageIconUrl,
tooltip: {
content: 'Open the stack layer menu',
- global: true,
- aladin
+ position: {
+ direction: 'top'
+ }
},
action(o) {
let toolWasShown = !self.panels["stack"].isHidden;
@@ -135,8 +128,9 @@ import { Toolbar } from "../Widgets/Toolbar";
iconURL: stackOverlayIconUrl,
tooltip: {
content: 'Open the overlays menu',
- global: true,
- aladin
+ position: {
+ direction: 'top'
+ }
},
action(o) {
let toolWasShown = !self.panels["overlay"].isHidden;
@@ -153,13 +147,21 @@ import { Toolbar } from "../Widgets/Toolbar";
}
}
}),
+ projection: new ProjectionActionButton(aladin, {
+ openDirection: self.options.direction === 'right' ? 'left' : 'right',
+ action(o) {
+ // executed before opening the ctx menu
+ self.closeAll();
+ }
+ }),
simbad: new SimbadPointer(aladin),
goto: ActionButton.createIconBtn({
iconURL: searchIcon,
tooltip: {
content: 'Search for where a celestial object is',
- global: true,
- aladin
+ position: {
+ direction: 'top'
+ }
},
action(o) {
let toolWasShown = !self.panels["goto"].isHidden;
@@ -176,34 +178,14 @@ import { Toolbar } from "../Widgets/Toolbar";
}
}
}),
- grid: ActionButton.createIconBtn({
- iconURL: gridIcon,
- tooltip: {
- content: 'Open the grid layer menu',
- global: true,
- aladin
- },
- action(o) {
- let toolWasShown = !self.panels["grid"].isHidden;
-
- self.closeAll();
-
- if (!toolWasShown) {
- self.panels["grid"]._show({
- position: {
- nextTo: self.controls['grid'],
- direction: self.options.direction === 'right' ? 'left' : 'right',
- }
- });
- }
- }
- }),
+ grid: new GridEnabler(aladin),
settings: ActionButton.createIconBtn({
iconURL: settingsIcon,
tooltip: {
content: 'Some general settings e.g. background color, reticle, windows to show',
- global: true,
- aladin
+ position: {
+ direction: 'top'
+ }
},
action(o) {
let toolWasShown = !self.panels["settings"].isHidden;
@@ -219,46 +201,7 @@ import { Toolbar } from "../Widgets/Toolbar";
});
}
}
- }),
- fullscreen: ActionButton.createIconBtn({
- iconURL: aladin.isInFullscreen ? restoreIcon : maximizeIcon,
- tooltip: {
- content: aladin.isInFullscreen ? 'Restore original size' : 'Full-screen',
- global: true,
- aladin
- },
- action(o) {
- aladin.toggleFullscreen(aladin.options.realFullscreen);
- let btn = self.controls['fullscreen'];
-
- if (aladin.isInFullscreen) {
- // make that div above other aladin lite divs (if there are...)
- aladin.aladinDiv.style.zIndex = 1
- btn.update({
- iconURL: restoreIcon,
- tooltip: {
- content: 'Restore original size',
- global: true,
- aladin
- }
- });
- } else {
- aladin.aladinDiv.style.removeProperty('z-index')
-
- btn.update({
- iconURL: maximizeIcon,
- tooltip: {
- content: 'Fullscreen',
- global: true,
- aladin
- }
- });
- }
-
- // hide all the controls
- self.closeAll()
- }
- }),
+ })
};
}
@@ -267,6 +210,8 @@ import { Toolbar } from "../Widgets/Toolbar";
let panel = this.panels[name];
panel && panel._hide();
}
+
+ this.controls.projection.hideMenu()
}
enable(name) {
diff --git a/src/js/gui/widgets/ActionButton.js b/src/js/gui/widgets/ActionButton.js
index 896db686..e9fa48c3 100644
--- a/src/js/gui/widgets/ActionButton.js
+++ b/src/js/gui/widgets/ActionButton.js
@@ -79,11 +79,6 @@ export class ActionButton extends DOMElement {
let el = document.createElement('button');
el.classList.add('aladin-btn');
- if (Utils.hasTouchScreen()) {
- // Add a little padding
- el.style.padding = "0.2em";
- }
-
// add it to the dom
super(el, options);
this._show();
@@ -101,6 +96,12 @@ export class ActionButton extends DOMElement {
this.removeClass('toggled');
}
+ if (this.options.size === 'small') {
+ this.addClass('small-sized-icon')
+ } else {
+ this.addClass('medium-sized-icon')
+ }
+
if (this.options.action) {
this.action = (e) => {
e.stopPropagation();
@@ -157,8 +158,13 @@ export class ActionButton extends DOMElement {
}
static createIconBtn(opt, target, position = 'beforeend') {
- let btn = new ActionButton(opt, target, position);
- btn.addClass('medium-sized-icon');
+ let btn = new ActionButton({...opt, size: 'medium'}, target, position);
+
+ return btn;
+ }
+
+ static createSmallSizedIconBtn(opt, target, position = 'beforeend') {
+ let btn = new ActionButton({...opt, size: 'small'}, target, position);
return btn;
}
diff --git a/src/js/gui/widgets/ContextMenu.js b/src/js/gui/widgets/ContextMenu.js
index 57c5ae4d..ece6696b 100644
--- a/src/js/gui/widgets/ContextMenu.js
+++ b/src/js/gui/widgets/ContextMenu.js
@@ -50,10 +50,14 @@ export class ContextMenu extends DOMElement {
this.cssStyleDefault = el.style;
- if (!options || options.hideOnClick === undefined || options.hideOnClick === true) {
+ if (!options || options.hideOnClick === undefined || options.hideOnClick === true || typeof options.hideOnClick === 'function') {
this.aladin.aladinDiv.addEventListener('click', (e) => {
if (!el.contains(e.target)) {
- this._hide()
+ if (options && options.hideOnClick && typeof options.hideOnClick === 'function') {
+ options.hideOnClick(e)
+ } else {
+ this._hide()
+ }
}
});
}
@@ -70,13 +74,15 @@ export class ContextMenu extends DOMElement {
})
}
} else {
- window.addEventListener('resize', () => {
+ new ResizeObserver(() => {
this._hide()
})
+ .observe(this.aladin.aladinDiv)
}
}
}
+ static lastHoveredItem;
_attachOption(target, opt, e, cssStyle) {
let item = document.createElement('li');
item.classList.add('aladin-context-menu-item');
@@ -110,9 +116,8 @@ export class ContextMenu extends DOMElement {
if (opt.label.icon) {
// add a button with a little bit of margin
let icon = new ActionButton({
- ...opt.label.icon,
+ ...{...opt.label.icon, size: 'small'},
});
- icon.addClass('medium-sized-icon');
layout.push(icon)
}
@@ -195,16 +200,17 @@ export class ContextMenu extends DOMElement {
}
});
} else if (opt.action) {
- item.addEventListener('click', o => {
- o.stopPropagation();
+ item.addEventListener('click', e => {
+ e.preventDefault();
+ e.stopPropagation();
if (!opt.disabled || opt.disabled === false) {
if (!opt.subMenu || opt.subMenu.length === 0) {
- opt.action(e);
-
if ((opt.mustHide === undefined || opt.mustHide === true) && (!self.options || self.options.hideOnClick === undefined || self.options.hideOnClick === true)) {
self._hide();
}
+
+ opt.action(e);
}
}
});
@@ -226,24 +232,37 @@ export class ContextMenu extends DOMElement {
opt.subMenu.forEach(subOpt => this._attachOption(subMenu, subOpt, e, cssStyle));
}
+ const areSiblings = (elm1, elm2) => (elm1 !== elm2 && elm1.parentNode == elm2.parentNode);
+ item.addEventListener('mouseover', e => {
+ e.stopPropagation();
+ e.preventDefault();
- if (opt.hover) {
- item.addEventListener('mouseover', e => {
- e.stopPropagation();
- e.preventDefault();
-
+ if (opt.hover) {
opt.hover(e, item);
- })
- }
+ }
- if (opt.unhover) {
- item.addEventListener('mouseout', e => {
- e.stopPropagation();
- e.preventDefault();
+ if (ContextMenu.lastHoveredItem) {
+ let parent = ContextMenu.lastHoveredItem.parentNode;
+ if (parent && (areSiblings(parent, item) || item.contains(parent) || item === parent)) {
+ ContextMenu.lastHoveredItem.style.display = 'none';
+ }
+ }
+ const subMenu = item.querySelector('.aladin-context-sub-menu');
+ if (subMenu) {
+ subMenu.style.display = 'block';
+ ContextMenu.lastHoveredItem = subMenu;
+ }
+ })
+
+ item.addEventListener('mouseout', e => {
+ e.stopPropagation();
+ e.preventDefault();
+
+ if (opt.unhover) {
opt.unhover(e, item);
- })
- }
+ }
+ })
target.appendChild(item);
}
diff --git a/src/js/gui/widgets/Input.js b/src/js/gui/widgets/Input.js
index 73f6b616..61ed427c 100644
--- a/src/js/gui/widgets/Input.js
+++ b/src/js/gui/widgets/Input.js
@@ -173,11 +173,11 @@ export class Input extends DOMElement {
Tooltip.add(this.options.tooltip, this)
}
- // Add padding for inputs except color ones
+ /*// Add padding for inputs except color ones
if (Utils.hasTouchScreen() && layout.type !== "color") {
// Add a little padding
this.el.style.padding = "0.5em";
- }
+ }*/
super._show()
}
diff --git a/src/js/gui/widgets/Selector.js b/src/js/gui/widgets/Selector.js
index 0e115a90..76767a01 100644
--- a/src/js/gui/widgets/Selector.js
+++ b/src/js/gui/widgets/Selector.js
@@ -78,13 +78,7 @@ export class SelectorButton extends DOMElement {
let optSelect = this.options[id];
menuOptions.push({
- label: new ActionButton(optSelect),
- cssStyle: {
- padding: 0,
- height: 'fit-content',
- margin: 0,
- border: 'none',
- },
+ label: ActionButton.createSmallSizedIconBtn(optSelect),
action(e) {
if(optSelect.change) {
optSelect.change(e)
@@ -140,10 +134,8 @@ export class SelectorButton extends DOMElement {
// remove from the DOM tree
const selectedId = this.options.selected;
let {target, position} = this.remove();
-
- this.el = new ActionButton({
+ this.el = ActionButton.createSmallSizedIconBtn({
...this.options[selectedId],
- tooltip: this.options.tooltip,
action: (e) => {
if (self.fsm.state === 'openCtxMenu') {
self.fsm.dispatch('closeCtxMenu');
diff --git a/src/js/gui/widgets/Tooltip.js b/src/js/gui/widgets/Tooltip.js
index 8e9a67e8..aca97a79 100644
--- a/src/js/gui/widgets/Tooltip.js
+++ b/src/js/gui/widgets/Tooltip.js
@@ -174,28 +174,19 @@ export class Tooltip extends DOMElement {
if (!statusBar) {
return;
}
- let removeMsgFunc = () => {
- statusBar.removeMessage('tooltip')
- }
- let timeoutId;
+
// handle global tooltip div display
Utils.on(target.el, 'mouseover', (e) => {
+ statusBar.removeMessage('tooltip')
statusBar.appendMessage({
id: 'tooltip',
message: options.content,
duration: 'unlimited',
type: 'tooltip'
})
- if (timeoutId) {
- clearTimeout(timeoutId)
- }
- timeoutId = setTimeout(removeMsgFunc, 1000)
});
Utils.on(target.el, 'mouseout', (e) => {
statusBar.removeMessage('tooltip')
- if (timeoutId) {
- clearTimeout(timeoutId)
- }
});
return;
}
diff --git a/src/js/gui/widgets/Widget.js b/src/js/gui/widgets/Widget.js
index b6d4c094..b6bb5cf1 100644
--- a/src/js/gui/widgets/Widget.js
+++ b/src/js/gui/widgets/Widget.js
@@ -145,8 +145,8 @@ export class DOMElement {
return;
}
- let left = 0, top = 0, bottom, right;
- let x, y;
+ let left, top, bottom, right;
+ let x = 0, y = 0;
// handle the anchor/dir case with higher priority
const {offsetWidth, offsetHeight} = el;
@@ -171,6 +171,19 @@ export class DOMElement {
if (options.right !== undefined) {
right = options.right;
}
+
+ if (typeof top === 'number') {
+ top = top + 'px';
+ }
+ if (typeof bottom === 'number') {
+ bottom = bottom + 'px';
+ }
+ if (typeof left === 'number') {
+ left = left + 'px';
+ }
+ if (typeof right === 'number') {
+ right = right + 'px';
+ }
} else if (options && options.nextTo && options.direction) {
let dir = options.direction || 'right';
let nextTo = options.nextTo;
@@ -207,47 +220,55 @@ export class DOMElement {
top = 0;
break;
}
- }
- // Translate if the div in
- if (left + offsetWidth > innerWidth) {
- x = '-' + (left + offsetWidth - innerWidth) + 'px';
- }
+ // Translate if the div in
+ if (left + offsetWidth > innerWidth) {
+ x = '-' + (left + offsetWidth - innerWidth) + 'px';
+ } else if (left < 0) {
+ x = Math.abs(left) + 'px';
+ }
- if (top + offsetHeight >= innerHeight) {
- y = '-' + (top + offsetHeight - innerHeight) + 'px';
- }
-
- if (left < 0) {
- x = Math.abs(left) + 'px';
- }
-
- if (top < 0) {
- y = Math.abs(top) + 'px';
+ if (top + offsetHeight >= innerHeight) {
+ y = '-' + (top + offsetHeight - innerHeight) + 'px';
+ } else if (top < 0) {
+ y = Math.abs(top) + 'px';
+ }
+
+ if (bottom) {
+ bottom = bottom + 'px';
+ }
+ if (top) {
+ top = top + 'px';
+ }
+ if (left) {
+ left = left + 'px';
+ }
+ if (right) {
+ right = right + 'px';
+ }
}
if (bottom !== undefined) {
- el.style.bottom = bottom + 'px';
- } else {
- el.style.top = top + 'px';
+ el.style.bottom = bottom;
+ }
+ if (top !== undefined) {
+ el.style.top = top;
+ }
+ if (left !== undefined) {
+ el.style.left = left;
}
-
if (right !== undefined) {
- el.style.right = right + 'px';
- } else {
- el.style.left = left + 'px';
+ el.style.right = right;
}
- if (x && y)
+ if (x && y) {
el.style.transform = `translate(${x}, ${y})`;
+ }
}
_show() {
this.el.style.display = 'block';
this.isHidden = false;
-
- // recursively
- //this._updateTooltipAfterInsertion();
}
_hide() {