From 5f3bb19bfa222ebb506d1a7f206f17ff6b3d8dbd Mon Sep 17 00:00:00 2001 From: Matthieu Baumann Date: Fri, 2 Feb 2024 14:29:44 +0100 Subject: [PATCH] ui fixes, testing --- examples/al-adass2022.html | 2 +- examples/al-easy-access-simbad-ned.html | 2 +- examples/al-gw.html | 4 +- examples/al-hips-order-list.html | 2 +- examples/al-moc-sdss9.html | 1 - examples/al-multiple-instances.html | 4 +- examples/al-panstarrs-id.html | 32 +++ src/core/src/app.rs | 5 +- src/core/src/grid/meridian.rs | 1 - src/core/src/grid/mod.rs | 11 +- src/core/src/healpix/coverage.rs | 4 + src/core/src/lib.rs | 24 ++- src/core/src/renderable/catalog/manager.rs | 11 +- src/core/src/renderable/coverage/hierarchy.rs | 6 +- src/core/src/renderable/coverage/mod.rs | 4 +- src/core/src/renderable/line/mod.rs | 2 +- src/css/aladin.css | 80 ++++--- src/js/A.js | 2 +- src/js/Aladin.js | 202 ++++++++++-------- src/js/FiniteStateMachine/PolySelect.js | 16 -- src/js/HiPSProperties.js | 28 +-- src/js/View.js | 58 ++--- src/js/gui/Box/CatalogQueryBox.js | 19 +- src/js/gui/Box/ConeSearchBox.js | 21 +- src/js/gui/Box/GotoBox.js | 7 +- src/js/gui/Box/GridBox.js | 10 +- src/js/gui/Box/HiPSSelectorBox.js | 46 ++-- src/js/gui/Box/ServiceQueryBox.js | 17 +- src/js/gui/Box/ShortLivedBox.js | 17 +- src/js/gui/Box/StatusBarBox.js | 19 +- src/js/gui/Box/SurveyEditBox.js | 31 ++- src/js/gui/Button/CtxMenuOpener.js | 47 +++- src/js/gui/Button/MainSurvey.js | 21 +- src/js/gui/Button/Projection.js | 4 +- src/js/gui/Button/ShareView.js | 2 +- src/js/gui/CtxMenu/OverlayStack.js | 27 +-- src/js/gui/CtxMenu/Settings.js | 5 +- src/js/gui/CtxMenu/SurveyCtxMenu.js | 144 ------------- src/js/gui/CtxMenu/SurveyStack.js | 201 +++++++++++++---- src/js/gui/FoV.js | 19 +- src/js/gui/Layout.js | 13 +- src/js/gui/Location.js | 19 +- src/js/gui/Toolbar/Menu.js | 112 +++++----- src/js/gui/widgets/ActionButton.js | 2 +- src/js/gui/widgets/Box.js | 14 +- src/js/gui/widgets/ContextMenu.js | 125 ++++++----- src/js/gui/widgets/Input.js | 7 + src/js/gui/widgets/Toolbar.js | 64 ++++-- src/js/gui/widgets/Widget.js | 47 ++-- 49 files changed, 852 insertions(+), 709 deletions(-) create mode 100644 examples/al-panstarrs-id.html delete mode 100644 src/js/gui/CtxMenu/SurveyCtxMenu.js diff --git a/examples/al-adass2022.html b/examples/al-adass2022.html index 872124ac..329ff98d 100644 --- a/examples/al-adass2022.html +++ b/examples/al-adass2022.html @@ -30,7 +30,7 @@ rotation += 0.07; aladin.setRotation(rotation) - aladin.setFov(fov); + aladin.setFoV(fov); if (fov < 3 && fov > 0.5) { let opacity = 1.0 - (fov - 0.5)/(3 - 0.5); diff --git a/examples/al-easy-access-simbad-ned.html b/examples/al-easy-access-simbad-ned.html index d663d06e..486c8f62 100644 --- a/examples/al-easy-access-simbad-ned.html +++ b/examples/al-easy-access-simbad-ned.html @@ -20,7 +20,7 @@ showSimbadPointerControl: false, showShareControl: true, showStatusBar: true, - showStackLayerControls: true, + showStackLayerControl: true, }); aladin.addCatalog(A.catalogFromSimbad('09 55 52.4 +69 40 47', 0.1, {onClick: 'showTable', limit: 1000})); diff --git a/examples/al-gw.html b/examples/al-gw.html index 73ecc1d6..fab63c51 100644 --- a/examples/al-gw.html +++ b/examples/al-gw.html @@ -10,9 +10,9 @@ import A from '../src/js/A.js'; //let aladin; A.init.then(() => { - aladin = A.aladin('#aladin-lite-div', {showReticle: true, projection: "TAN", target: '15 16 57.636 -60 55 7.49', showProjectionControl: true, realFullscreen: true, showZoomControl: true, showSimbadPointerControl: true, showShareControl: true, showContextMenu: true, showCooGridControl: true, fullScreen: true, showCooGrid: true, fov: 90}); + aladin = A.aladin('#aladin-lite-div', {showReticle: true, showSurveyStackControl: true, showOverlayStackControl: false, projection: "TAN", target: '15 16 57.636 -60 55 7.49', showProjectionControl: true, realFullscreen: true, showZoomControl: true, showSimbadPointerControl: true, showShareControl: true, showContextMenu: true, showCooGridControl: true, fullScreen: true, showCooGrid: true, fov: 90}); - var moc_0_99 = A.MOCFromURL("./gw/gw_0.9.fits",{ name: "GW 90%", color: "#ff0000", opacity: 0.5, lineWidth: 3, fill: true, perimeter: true}); + var moc_0_99 = A.MOCFromURL("./gw/gw_0.9.fits",{ name: "GW 90%", color: "#ff0000", opacity: 0.0, lineWidth: 3, fill: false, perimeter: true}); var moc_0_95 = A.MOCFromURL("./gw/gw_0.6.fits",{ name: "GW 60%", color: "#00ff00", opacity: 0.5, lineWidth: 3, fill: true, perimeter: true}); var moc_0_5 = A.MOCFromURL("./gw/gw_0.3.fits",{ name: "GW 30%", color: "#00ffff", opacity: 0.5, lineWidth: 3, fill: true, perimeter: true}); var moc_0_2 = A.MOCFromURL("./gw/gw_0.1.fits",{ name: "GW 10%", color: "#ff00ff", opacity: 0.5, lineWidth: 3, fill: true, perimeter: true}); diff --git a/examples/al-hips-order-list.html b/examples/al-hips-order-list.html index d4b47131..9d5f78a3 100644 --- a/examples/al-hips-order-list.html +++ b/examples/al-hips-order-list.html @@ -10,7 +10,7 @@ import A from '../src/js/A.js'; let aladin; A.init.then(() => { - aladin = A.aladin('#aladin-lite-div', {survey: 'http://alasky.cds.unistra.fr/ancillary/GaiaDR2/hips-density-map/', showProjectionControl: true, showContextMenu: true, fullScreen: true, target: 'galactic center'}); + aladin = A.aladin('#aladin-lite-div', {survey: 'http://alasky.cds.unistra.fr/ancillary/GaiaDR2/hips-density-map/', showProjectionControl: true, showContextMenu: true, showStatusBar: true, fullScreen: true, target: 'galactic center'}); const fluxMap = aladin.createImageSurvey('gdr3-color-flux-map', 'Gaia DR3 flux map', 'https://alasky.u-strasbg.fr/ancillary/GaiaEDR3/color-Rp-G-Bp-flux-map', 'equatorial', 7); const densityMap = aladin.createImageSurvey('gdr3-density-map', 'Gaia DR3 density map', 'sdfsg', 'equatorial', 7, {imgFormat: 'fits'}); diff --git a/examples/al-moc-sdss9.html b/examples/al-moc-sdss9.html index 0459536a..56d32c55 100644 --- a/examples/al-moc-sdss9.html +++ b/examples/al-moc-sdss9.html @@ -16,7 +16,6 @@ // moc is ready console.log(moc.contains(205.9019247, +2.4492764)); console.log(moc.contains(-205.9019247, +2.4492764)); - }); var moc10 = A.MOCFromURL('https://alasky.unistra.fr/MocServer/query?ivorn=ivo%3A%2F%2FCDS%2FV%2F139%2Fsdss9&get=moc&order=11&fmt=fits', {color: '#ffffff', perimeter: true, fillColor: '#aabbcc', opacity: 0.1, lineWidth: 3}); var moc9 = A.MOCFromURL('https://alasky.unistra.fr/MocServer/query?ivorn=ivo%3A%2F%2FCDS%2FV%2F139%2Fsdss9&get=moc&order=4&fmt=fits', {color: '#00ff00', opacity: 0.5, lineWidth: 3, perimeter: true}); diff --git a/examples/al-multiple-instances.html b/examples/al-multiple-instances.html index abf98e48..5e402499 100644 --- a/examples/al-multiple-instances.html +++ b/examples/al-multiple-instances.html @@ -14,8 +14,8 @@ let al2; A.init.then(() => { // Start up Aladin Lite - al1 = A.aladin('#al1', {target: 'M51', fov: 0.3, survey: 'P/DSS2/color', fullScreen: false}); - al2 = A.aladin('#al2', {target: 'M51', fov: 180, survey: 'P/PanSTARRS/DR1/z', fullScreen: false}); + al1 = A.aladin('#al1', {target: 'M51', fov: 0.3, survey: 'P/DSS2/color', fullScreen: false, showContextMenu: true, showShareControl: true}); + al2 = A.aladin('#al2', {target: 'M51', fov: 180, survey: 'P/PanSTARRS/DR1/z', fullScreen: false, showContextMenu: true, showShareControl: true}); }); diff --git a/examples/al-panstarrs-id.html b/examples/al-panstarrs-id.html new file mode 100644 index 00000000..de191c46 --- /dev/null +++ b/examples/al-panstarrs-id.html @@ -0,0 +1,32 @@ + + + + + + +
+ + + + + diff --git a/src/core/src/app.rs b/src/core/src/app.rs index 749646f3..88a847ce 100644 --- a/src/core/src/app.rs +++ b/src/core/src/app.rs @@ -480,7 +480,7 @@ impl App { Ok(res) } - pub(crate) fn get_moc(&self, cfg: &al_api::moc::MOC) -> Option<&MOC> { + pub(crate) fn get_moc(&self, cfg: &al_api::moc::MOC) -> Option<&HEALPixCoverage> { self.moc.get_hpx_coverage(cfg) } @@ -489,9 +489,6 @@ impl App { mut cfg: al_api::moc::MOC, moc: HEALPixCoverage, ) -> Result<(), JsValue> { - // change the moc thickness - cfg.line_width = (cfg.line_width + 0.5) * 2.0 / self.camera.get_width(); - self.moc .push_back(moc, cfg, &mut self.camera, &self.projection); self.request_redraw = true; diff --git a/src/core/src/grid/meridian.rs b/src/core/src/grid/meridian.rs index 17003d51..28f69f7b 100644 --- a/src/core/src/grid/meridian.rs +++ b/src/core/src/grid/meridian.rs @@ -10,7 +10,6 @@ use crate::ProjectionType; use crate::grid::angle::SerializeFmt; use crate::math::HALF_PI; - pub fn get_intersecting_meridian( lon: f64, camera: &CameraViewPort, diff --git a/src/core/src/grid/mod.rs b/src/core/src/grid/mod.rs index a8777108..c1b04e3c 100644 --- a/src/core/src/grid/mod.rs +++ b/src/core/src/grid/mod.rs @@ -15,6 +15,7 @@ use crate::ProjectionType; use al_api::color::ColorRGBA; use al_api::grid::GridCfg; +use cgmath::InnerSpace; use crate::grid::label::Label; pub struct ProjetedGrid { @@ -53,7 +54,7 @@ impl ProjetedGrid { let label_scale = 1.0; let line_style = line::Style::None; let fmt = angle::SerializeFmt::DMS; - let thickness = 3.0; + let thickness = 2.0; let grid = ProjetedGrid { color, @@ -207,12 +208,8 @@ impl ProjetedGrid { vertices, }); - rasterizer.add_stroke_paths( - paths, - self.thickness * 2.0 / camera.get_width(), - &self.color, - &self.line_style, - ); + let m = camera.get_screen_size().magnitude(); + rasterizer.add_stroke_paths(paths, self.thickness, &self.color, &self.line_style); // update labels { diff --git a/src/core/src/healpix/coverage.rs b/src/core/src/healpix/coverage.rs index 94e61728..424064c0 100644 --- a/src/core/src/healpix/coverage.rs +++ b/src/core/src/healpix/coverage.rs @@ -78,6 +78,10 @@ impl HEALPixCoverage { self.0.is_in(lon.0, lat.0) } + pub fn contains_lonlat(&self, lonlat: &LonLatT) -> bool { + self.0.is_in(lonlat.lon().0, lonlat.lat().0) + } + // O(log2(N)) pub fn intersects_cell(&self, cell: &HEALPixCell) -> bool { let z29_rng = cell.z_29_rng(); diff --git a/src/core/src/lib.rs b/src/core/src/lib.rs index 27bef9d6..dd1b5754 100644 --- a/src/core/src/lib.rs +++ b/src/core/src/lib.rs @@ -977,13 +977,15 @@ impl WebClient { dec_deg: f64, rad_deg: f64, ) -> Result<(), JsValue> { + let tile_d = self.app.get_norder(); + let pixel_d = tile_d + 9; let moc = HEALPixCoverage::from_cone( &LonLatT::new( ra_deg.to_radians().to_angle(), dec_deg.to_radians().to_angle(), ), rad_deg.to_radians(), - 10, + pixel_d as u8 - 2, ); self.app.add_moc(params.clone(), moc)?; @@ -999,6 +1001,8 @@ impl WebClient { dec_deg: &[f64], ) -> Result<(), JsValue> { use cgmath::InnerSpace; + let tile_d = self.app.get_norder(); + let pixel_d = tile_d + 9; let vertex_it = ra_deg .iter() @@ -1010,7 +1014,7 @@ impl WebClient { let v_in = &Vector4::new(1.0, 0.0, 0.0, 1.0); - let mut moc = HEALPixCoverage::from_3d_coos(10, vertex_it, &v_in); + let mut moc = HEALPixCoverage::from_3d_coos(pixel_d as u8 - 2, vertex_it, &v_in); if moc.sky_fraction() > 0.5 { moc = moc.not(); } @@ -1037,21 +1041,23 @@ impl WebClient { #[wasm_bindgen(js_name = mocContains)] pub fn moc_contains( &mut self, - _params: &al_api::moc::MOC, - _lon: f64, - _lat: f64, + params: &al_api::moc::MOC, + lon: f64, + lat: f64, ) -> Result { - /*let moc = self.app.get_moc(params).ok_or_else(|| JsValue::from(js_sys::Error::new("MOC not found")))?; + let moc = self + .app + .get_moc(params) + .ok_or_else(|| JsValue::from(js_sys::Error::new("MOC not found")))?; let location = LonLatT::new(ArcDeg(lon).into(), ArcDeg(lat).into()); - Ok(moc.is_in(location.lon().0, location.lat().0))*/ - Ok(false) + Ok(moc.contains_lonlat(&location)) } #[wasm_bindgen(js_name = getMOCSkyFraction)] pub fn get_moc_sky_fraction(&mut self, params: &al_api::moc::MOC) -> f32 { if let Some(moc) = self.app.get_moc(params) { - moc.sky_fraction() + moc.sky_fraction() as f32 } else { 0.0 } diff --git a/src/core/src/renderable/catalog/manager.rs b/src/core/src/renderable/catalog/manager.rs index b95d9469..669c345e 100644 --- a/src/core/src/renderable/catalog/manager.rs +++ b/src/core/src/renderable/catalog/manager.rs @@ -32,7 +32,7 @@ impl From for JsValue { const NUM_SHAPES: usize = 5; pub struct Manager { gl: WebGlContext, - kernels: HashMap<&'static str, Texture2D>, + //kernels: HashMap<&'static str, Texture2D>, fbo: FrameBufferObject, @@ -72,7 +72,7 @@ impl Manager { WebGl2RenderingContext::CLAMP_TO_EDGE, ), ]; - let kernels = [ + /*let kernels = [ ( "gaussian", Texture2D::create_from_path::<_, RGBA8U>(gl, "kernel", &kernel_filename, params)?, @@ -98,8 +98,7 @@ impl Manager { )?, ), ] - .into(); - + .into();*/ // Create the VAO for the screen let vertex_array_object_screen = { let vertices = [ @@ -168,7 +167,7 @@ impl Manager { let gl = gl.clone(); let mut manager = Manager { gl, - kernels, + //kernels, fbo, @@ -514,7 +513,7 @@ impl Catalog { shader_bound .attach_uniforms_from(camera) // Attach catalog specialized uniforms - .attach_uniform("kernel_texture", &manager.kernels["gaussian"]) // Gaussian kernel texture + //.attach_uniform("kernel_texture", &manager.kernels["gaussian"]) // Gaussian kernel texture .attach_uniform("strength", &self.strength) // Strengh of the kernel .attach_uniform("current_time", &utils::get_current_time()) .attach_uniform("kernel_size", &manager.kernel_size) diff --git a/src/core/src/renderable/coverage/hierarchy.rs b/src/core/src/renderable/coverage/hierarchy.rs index 1d054f3f..72f38e52 100644 --- a/src/core/src/renderable/coverage/hierarchy.rs +++ b/src/core/src/renderable/coverage/hierarchy.rs @@ -6,6 +6,7 @@ pub struct MOCHierarchy { full_res_depth: u8, // MOC at different resolution mocs: Vec, + coverage: HEALPixCoverage, } impl MOCHierarchy { @@ -21,6 +22,7 @@ impl MOCHierarchy { Self { mocs, full_res_depth, + coverage: full_res_moc, } } @@ -63,8 +65,8 @@ impl MOCHierarchy { &mut self.mocs[d] } - pub fn get_full_moc(&self) -> &MOC { - &self.mocs[self.full_res_depth as usize] + pub fn get_full_moc(&self) -> &HEALPixCoverage { + &self.coverage } pub fn get_full_res_depth(&self) -> u8 { diff --git a/src/core/src/renderable/coverage/mod.rs b/src/core/src/renderable/coverage/mod.rs index 6bdb20d1..664bb841 100644 --- a/src/core/src/renderable/coverage/mod.rs +++ b/src/core/src/renderable/coverage/mod.rs @@ -223,11 +223,11 @@ impl MOCRenderer { //self.layers.push(key); } - pub fn get_hpx_coverage(&self, cfg: &Cfg) -> Option<&MOC> { + pub fn get_hpx_coverage(&self, cfg: &Cfg) -> Option<&HEALPixCoverage> { let name = cfg.get_uuid(); if let Some(idx) = self.cfgs.iter().position(|cfg| cfg.get_uuid() == name) { - Some(self.mocs[idx].get_full_moc()) + Some(&self.mocs[idx].get_full_moc()) } else { None } diff --git a/src/core/src/renderable/line/mod.rs b/src/core/src/renderable/line/mod.rs index ed149bc2..b8a9fe51 100644 --- a/src/core/src/renderable/line/mod.rs +++ b/src/core/src/renderable/line/mod.rs @@ -253,7 +253,7 @@ impl RasterizedLineRenderer { tessellator .tessellate( &p, - &StrokeOptions::default().with_line_width(thickness), + &StrokeOptions::default().with_line_width(thickness * 0.001), &mut BuffersBuilder::new(&mut geometry, |vertex: StrokeVertex| { vertex.position().to_array() }) diff --git a/src/css/aladin.css b/src/css/aladin.css index 0587f16c..898613a6 100644 --- a/src/css/aladin.css +++ b/src/css/aladin.css @@ -18,21 +18,18 @@ body { overscroll-behavior: contain; } .aladin-imageCanvas { position: relative; - z-index: 1; left: 0; top: 0; } .aladin-gridCanvas { position: absolute; - z-index: 1; left: 0; top: 0; } .aladin-catalogCanvas { position: absolute; - z-index: 2; left: 0; top: 0; } @@ -41,7 +38,6 @@ body { overscroll-behavior: contain; } position: absolute; bottom: 2px; right: 5px; - z-index: 20; min-width: 32px; max-width: 90px; @@ -76,7 +72,6 @@ body { overscroll-behavior: contain; } } .aladin-projection-select { - z-index: 20; position:absolute; top: 0px; right: 48px; @@ -91,8 +86,6 @@ body { overscroll-behavior: contain; } } .aladin-measurement-div { - z-index: 77; - /*font-family: monospace;*/ font-size: 12px; display: flex; @@ -240,7 +233,7 @@ word-wrap:break-word; position: absolute; top: 6px; right: 3px; - z-index: 20; + width: 30px; height: 30px; background-image: url('data:image/gif;base64,R0lGODlhFgAWAOMJAAAAAAEBAQICAgMDAwUFBAUFBQcHBwgICAsLCv///////////////////////////yH5BAEKAA8ALAAAAAAWABYAAARm8MlJabr41i0T+CCQcJz3CYMwklsSEAUhspVnHEYw0x1w558VzYQTBXm24sgjJCUQykmT9dzxWlNq9vrwILYtqe/wRc6SBqszOE6DLZ/AT00FyKNcD4wQeLdQAiB+cCFHVxkZXA8RADs='); @@ -253,7 +246,7 @@ word-wrap:break-word; top: 30px; left: 4px; cursor:pointer; - z-index: 20; + background: rgba(250, 250, 250, 0.8); border-radius: 4px; } @@ -274,7 +267,7 @@ word-wrap:break-word; position: absolute; left: 4px; cursor:pointer; - z-index: 20; + background: rgba(250, 250, 250, 0.8); border-radius: 2px; } @@ -305,7 +298,7 @@ word-wrap:break-word; .aladin-box { display: none; - z-index: 30; + padding: 4px 4px; background: whitesmoke; border-radius: 2px; @@ -340,7 +333,6 @@ word-wrap:break-word; .aladin-dialog { display: none; - z-index: 30; position: absolute; top: 50%; left: 50%; @@ -393,7 +385,6 @@ canvas { position: absolute; left: 4px; cursor:pointer; - z-index: 20; background: rgba(250, 250, 250, 0.8); border-radius: 2px; } @@ -424,7 +415,7 @@ canvas { position: absolute; left: 4px; cursor:pointer; - z-index: 20; + background: rgba(250, 250, 250, 0.8); border-radius: 2px; } @@ -446,7 +437,6 @@ canvas { bottom: 30px; left: 4px; cursor:pointer; - z-index: 20; background: rgba(250, 250, 250, 0.8); border-radius: 2px; } @@ -542,7 +532,7 @@ canvas { position: absolute; top: 6px; right: 3px; - z-index: 20; + width: 30px; height: 30px; background-image: url('data:image/gif;base64,R0lGODlhFgAWAOMJAAAAAAEBAQICAgMDAwUFBAUFBQcHBwgICAsLCv///////////////////////////yH5BAEKAA8ALAAAAAAWABYAAARk8MlJ60zJapsAyhsFPp1xfKHUZeVhAOPWwYD5xjIABDacXrseLtQhFAiBIVEwEOh8P9VzquRgrhgrNhudTaHdJ1NQ1SQCRgL41zIE1sSa6w0361y0eqXtW7EReCNlIgh6XYMbEQA7'); @@ -552,7 +542,7 @@ canvas { .aladin-fullscreen { position: fixed !important; - z-index: 9999; + top: 0; left: 0; height: 100% !important; @@ -563,7 +553,7 @@ canvas { } .aladin-zoomControl { - z-index: 20; + position:absolute; top: 50%; height: 48px; @@ -607,7 +597,8 @@ canvas { margin-bottom: 0; margin: 0; padding: 4px; - z-index: 30; + + z-index: 10; font-size: 12px; font-weight: normal; @@ -687,7 +678,7 @@ canvas { display: flex; align-items: center; justify-content: space-between; - z-index: 9000; + position: absolute; top: 0px; left: 0px; @@ -701,7 +692,6 @@ canvas { .aladin-fov, .aladin-location, .aladin-cooFrame { font-family: monospace; - z-index: 20; border: 1px solid white; border-radius: 3px; @@ -711,7 +701,7 @@ canvas { } .aladin-zoom-controls { - z-index: 20; + } .aladin-cancelBtn { @@ -749,6 +739,14 @@ canvas { flex-direction: column; } +.aladin-vertical-list.left { + align-items: flex-start; +} + +.aladin-vertical-list.right { + align-items: flex-end; +} + .aladin-horizontal-list { display: flex; align-items: center; @@ -806,7 +804,7 @@ canvas { } .aladin-window-container { - z-index: 25; + position: absolute; left: 0; bottom: 300px; @@ -826,7 +824,7 @@ canvas { } .aladin-popup-container { - z-index: 25; + position: absolute; width: 200px; display: none; @@ -969,6 +967,7 @@ canvas { left: 100%; display: none; width: max-content; + z-index: 20; } .aladin-context-sub-menu, @@ -976,7 +975,8 @@ canvas { position: absolute; background: #fff; color: #000; - z-index: 100; + + width: max-content; margin: 0; padding: 0; @@ -997,13 +997,15 @@ canvas { border-bottom: 1px solid #d2d2d2; border-left: 1px solid #d2d2d2; border-right: 1px solid #d2d2d2; + + color: lightgray; + background-color: black; } .aladin-context-menu .aladin-context-menu-item.aladin-context-menu-item-disabled { cursor: not-allowed; - background: #eee; + color: red; - z-index: 100; height: 22px; display: flex; @@ -1019,9 +1021,8 @@ canvas { .aladin-context-menu-item:hover { - background-color: rgba(0, 0, 0, 0.1); /* For default ctx menu */ - /*filter: brightness(150%); *//* For ctx menus having background images */ - z-index: 20; /* This is for the tooltip to appear outside the item, i.e. over the sibling item */ + /* This is for the tooltip to appear outside the item, i.e. over the sibling item */ + color: white; } .aladin-context-menu .aladin-context-menu-item span { @@ -1036,17 +1037,13 @@ canvas { margin-top: -1px; } -.aladin-context-menu .context-menu-item:hover { - background: #d2d2d2; -} - .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%); + left: 0; + transform: translateX(-100%); } .aladin-context-menu.top .aladin-context-sub-menu { @@ -1060,7 +1057,7 @@ canvas { .aladin-reticle { position: absolute; - z-index: 20; + top: 50%; left: 50%; transform: translate(-50%, -50%); @@ -1229,8 +1226,6 @@ canvas { /* take the size of its inner div child */ float: left; - - z-index: 10000; } .aladin-tooltip-container .aladin-tooltip { @@ -1245,10 +1240,12 @@ canvas { border-radius: 2px; top:0%; + + z-index: 100; /* Position the tooltip text - see examples below! */ position: absolute; - z-index: 10000; + /*font-family: Verdana, Geneva, Tahoma, sans-serif;*/ font-size: 12px; } @@ -1276,7 +1273,6 @@ canvas { left: 100%; } - /* *********************************************** */ /* Cursors */ @@ -1292,7 +1288,7 @@ canvas { /* Autocomplete styles (adapted from https://github.com/kraaden/autocomplete ) */ .autocomplete { background: white; - z-index: 20000; + font: 14px/22px "-apple-system", BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; overflow: auto; box-sizing: border-box; diff --git a/src/js/A.js b/src/js/A.js index 5f778fb4..0ce3f52c 100644 --- a/src/js/A.js +++ b/src/js/A.js @@ -40,7 +40,7 @@ import { Coo } from "./libs/astro/coo.js"; import { URLBuilder } from "./URLBuilder.js"; import { ColorCfg } from './ColorCfg.js'; import { Footprint } from './Footprint.js'; -import { Toolbar } from "./gui/widgets/Toolbar.js"; +import { Toolbar } from "./gui/Widgets/Toolbar.js"; import { Aladin } from "./Aladin.js"; import { ALEvent } from "./events/ALEvent.js"; // Wasm top level import diff --git a/src/js/Aladin.js b/src/js/Aladin.js index 3f3a9926..df390606 100644 --- a/src/js/Aladin.js +++ b/src/js/Aladin.js @@ -60,8 +60,7 @@ 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 { ConeSearchBox } from "./gui/Box/ConeSearchBox.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"; @@ -78,7 +77,9 @@ import { StatusBarBox } from "./gui/Box/StatusBarBox.js"; * @property {string} [backgroundColor="rgb(60, 60, 60)"] - Background color in RGB format. * * @property {boolean} [showZoomControl=true] - Whether to show the zoom control toolbar. - * @property {boolean} [showLayersControl=true] - Whether to show the layers control toolbar. + * @property {boolean} [showLayersControl=false] - Whether to show the layers control toolbar. + * @property {boolean} [showOverlayStackControl=true] - Whether to show the overlay stack control toolbar. + * @property {boolean} [showSurveyStackControl=true] - Whether to show the survey stack control toolbar. * @property {boolean} [showFullscreenControl=true] - Whether to show the fullscreen control toolbar. * @property {boolean} [showGotoControl=true] - Whether to show the goto control toolbar. * @property {boolean} [showSimbadPointerControl=false] - Whether to show the Simbad pointer control toolbar. @@ -170,9 +171,6 @@ export let Aladin = (function () { // parent div aladinDiv.classList.add("aladin-container"); - // Aladin logo - new AladinLogo(aladinDiv); - // measurement table this.measurementTable = new MeasurementTable(aladinDiv); @@ -181,7 +179,12 @@ export let Aladin = (function () { // set different options // Reticle this.view = new View(this); + + // Aladin logo + new AladinLogo(this.aladinDiv); + this.reticle = new Reticle(this.options, this); + this.popup = new Popup(this.aladinDiv, this.view); this.cacheSurveys = new Map(); this.ui = []; @@ -318,56 +321,6 @@ export let Aladin = (function () { Aladin.prototype._setupUI = function(options) { let self = this; - let textField = Input.text({ - label: "Go to:", - name: "goto", - type: "text", - placeholder: 'Object name/position', - //autocapitalize: 'off', - autocomplete: 'off', - autofocus: true, - actions: { - change: (e, input) => { - input.addEventListener('blur', (f) => {}); - }, - click: (e) => { - e.preventDefault(); - e.stopPropagation(); - - console.log("click") - } - /*focus: (e) => { - //e.stopPropagation(); - //e.preventDefault(); - - //textField.element().blur(); - - console.log("focus") - }, - input: (e) => { - console.log("change") - } - keydown: (e) => { - textField.removeClass('aladin-unknownObject'); // remove red border - - if (e.key === 'Enter') { - let object = textField.get(); - textField.el.blur(); - - aladin.gotoObject( - object, - { - error: function () { - textField.addClass('aladin-unknownObject'); - } - } - ); - - } - }*/ - } - }); - let viewport = A.toolbar({ direction: 'horizontal', position: { @@ -375,11 +328,6 @@ export let Aladin = (function () { } }, this); - // Add the projection control - if (options.showProjectionControl) { - viewport.add(new ProjectionActionButton(self)) - } - // Add the frame control if (options.showFrame) { let cooFrame = CooFrameEnum.fromString(options.cooFrame, CooFrameEnum.J2000); @@ -400,40 +348,45 @@ export let Aladin = (function () { }); cooFrameControl.addClass('aladin-cooFrame'); + viewport.add(cooFrameControl) } // Add the location info if (options.showCooLocation) { - viewport.add(new Location(this)); + this.location = new Location(this) + viewport.add(this.location); } // Add the FoV info if (options.showFov) { - viewport.appendAtLast(new FoV(this)) + viewport.add(new FoV(this)) + } + + // Add the projection control + if (options.showProjectionControl) { + viewport.add(new ProjectionActionButton(self), 'proj') } //////////////////////////////////////////////////// let menu = new Menu({ - direction: 'vertical', + orientation: 'vertical', + direction: 'right', position: { anchor: 'right top' } }, this); - /*let box = ConeSearchBox.getInstance(this); - box.attach({ - callback: (cs) => { - }, - position: { - anchor: 'center center', - } - }) - box._show();*/ - // Add the layers control if (options.showLayersControl) { - menu.enable('survey') menu.enable('stack') menu.enable('overlay') + } else { + if (options.showSurveyStackControl) { + menu.enable('stack') + } + + if (options.showOverlayStackControl) { + menu.enable('overlay') + } } // Add the simbad pointer control if (options.showSimbadPointerControl) { @@ -456,18 +409,18 @@ export let Aladin = (function () { menu.enable('fullscreen') } - this.addUI(menu); this.addUI(viewport); + this.addUI(menu); // share control panel if (options.showShareControl) { let share = A.toolbar({ - direction: 'horizontal', + orientation: 'horizontal', position: { anchor: 'left bottom' } }, this); - share.add(new ShareActionButton(this)) + share.add(new ShareActionButton(self)) share.add(new SnapshotActionButton({ tooltip: { content: 'Take a snapshot of your current view', @@ -517,14 +470,14 @@ export let Aladin = (function () { minusZoomBtn.addClass('medium-sized-icon') let zoomControlToolbar = A.toolbar({ - layout: [plusZoomBtn, minusZoomBtn], - direction: 'vertical', + orientation: 'vertical', position: { anchor: 'left center', } }); zoomControlToolbar.addClass('aladin-zoom-controls'); - + zoomControlToolbar.add([plusZoomBtn, minusZoomBtn]) + this.addUI(zoomControlToolbar) } @@ -532,6 +485,76 @@ export let Aladin = (function () { if (options.showStatusBar) { this.statusBar = new StatusBarBox(this); } + + this.menu = menu; + this.viewportMenu = viewport; + + this._applyMediaQueriesUI() + } + + Aladin.prototype._applyMediaQueriesUI = function() { + let self = this; + function updateLocation() { + let [lon, lat] = self.wasm.getCenter(); + self.location.update({ + lon: lon, + lat: lat, + isViewCenter: true, + frame: self.view.cooFrame + }, self); + } + + function mqMediumSizeFunction(x) { + if (x.matches) { // If media query matches + if (self.location) { + Location.prec = 2; + updateLocation() + } + } else { + if (self.location) { + Location.prec = 7; + updateLocation() + } + } + } + + // Create a MediaQueryList object + var mqMediumSize = window.matchMedia("(max-width: 500px)") + + // Attach listener function on state changes + mqMediumSize.addEventListener("change", function() { + mqMediumSizeFunction(mqMediumSize); + }); + + var mqSmallSize = window.matchMedia("(max-width: 410px)") + + function mqSmallSizeFunction(x) { + if (x.matches) { // If media query matches + self.menu.update({ + direction: 'left', + position: { + top: 23, + left: 0 + } + }) + } else { + self.menu.update({ + direction: 'right', + position: { + anchor: 'right top' + } + }) + } + } + + // Attach listener function on state changes + mqSmallSize.addEventListener("change", function() { + mqSmallSizeFunction(mqSmallSize); + }); + + // Call listener function at run time + mqSmallSizeFunction(mqSmallSize); + mqMediumSizeFunction(mqMediumSize); } /**** CONSTANTS ****/ @@ -553,7 +576,9 @@ export let Aladin = (function () { // Zoom toolbar showZoomControl: true, // Menu toolbar - showLayersControl: true, + showLayersControl: false, + showOverlayStackControl: true, + showSurveyStackControl: true, showFullscreenControl: true, showGotoControl: true, showSimbadPointerControl: false, @@ -576,7 +601,7 @@ export let Aladin = (function () { showCatalog: true, // TODO: still used ?? fullScreen: false, - reticleColor: "rgb(255, 200, 0)", + reticleColor: "rgb(178, 50, 178)", reticleSize: 22, gridColor: "rgb(0, 255, 0)", gridOpacity: 0.5, @@ -793,6 +818,7 @@ export let Aladin = (function () { return; } this.view.setProjection(projection); + ALEvent.PROJECTION_CHANGED.dispatchedTo(this.aladinDiv, {projection: projection}); }; @@ -1901,11 +1927,11 @@ export let Aladin = (function () { this.view.overlayForPopup.show(); this.view.catalogForPopup.show(); - this.view.popup.setTitle(title); - this.view.popup.setText(content); + this.popup.setTitle(title); + this.popup.setText(content); - this.view.popup.setSource(marker); - this.view.popup.show(); + this.popup.setSource(marker); + this.popup.show(); }; // @API @@ -1913,7 +1939,7 @@ export let Aladin = (function () { * hide popup */ Aladin.prototype.hidePopup = function () { - this.view.popup.hide(); + this.popup.hide(); }; // @API diff --git a/src/js/FiniteStateMachine/PolySelect.js b/src/js/FiniteStateMachine/PolySelect.js index 8d1b352a..be1ced3c 100644 --- a/src/js/FiniteStateMachine/PolySelect.js +++ b/src/js/FiniteStateMachine/PolySelect.js @@ -39,8 +39,6 @@ export class PolySelect extends FSM { constructor(options, view) { // Off initial state let off = () => { - console.log("off") - view.aladin.showReticle(true) view.setMode(View.PAN) view.setCursor('default'); @@ -51,8 +49,6 @@ export class PolySelect extends FSM { } let btn; let mouseout = (params) => { - console.log("mouseout") - let {e, coo} = params; if (btn.el.contains(e.relatedTarget) || e.relatedTarget.contains(btn.el)) { @@ -66,8 +62,6 @@ export class PolySelect extends FSM { }; let start = (params) => { - console.log("start") - const {callback} = params; view.aladin.showReticle(false) view.setCursor('crosshair'); @@ -80,8 +74,6 @@ export class PolySelect extends FSM { } let click = (params) => { - console.log("click") - const {coo} = params; const firstClick = this.coos.length === 0; @@ -115,9 +107,6 @@ export class PolySelect extends FSM { }; let mousemove = (params) => { - - console.log("move") - const {coo} = params; this.moveCoo = coo; @@ -125,9 +114,6 @@ export class PolySelect extends FSM { }; let draw = () => { - - console.log("draw") - let ctx = view.catalogCtx; if (!view.catalogCanvasCleared) { @@ -158,8 +144,6 @@ export class PolySelect extends FSM { } let finish = () => { - console.log("finish") - // finish the selection let xMin = this.coos[0].x let yMin = this.coos[0].y diff --git a/src/js/HiPSProperties.js b/src/js/HiPSProperties.js index e8bf8c9b..3833f03a 100644 --- a/src/js/HiPSProperties.js +++ b/src/js/HiPSProperties.js @@ -112,20 +112,20 @@ HiPSProperties.fetchFromUrl = async function(urlOrId) { return response.text(); } }) - .then((response) => { - // We get the property here - let metadata = HiPSDefinition.parseHiPSProperties(response); - - // 1. Ensure there is exactly one survey matching - if (metadata) { - // Set the service url if not found - metadata.hips_service_url = HiPSServiceUrl; - - return metadata; - } else { - throw 'No surveys matching at this url: ' + rootURL; - } - }) + .then( + (response) => new Promise((resolve, reject) => { + // We get the property here + let metadata = HiPSDefinition.parseHiPSProperties(response); + // 1. Ensure there is exactly one survey matching + if (metadata && Object.keys(metadata).length > 0) { + // Set the service url if not found + metadata.hips_service_url = HiPSServiceUrl; + resolve(metadata); + } else { + reject('No surveys matching at this url: ' + rootURL); + } + }) + ) return result; } diff --git a/src/js/View.js b/src/js/View.js index c5d4e8b5..3f0916dd 100644 --- a/src/js/View.js +++ b/src/js/View.js @@ -31,7 +31,6 @@ import { Aladin } from "./Aladin.js"; import A from "./A.js"; -import { Popup } from "./Popup.js"; import { HealpixGrid } from "./HealpixGrid.js"; import { ProjectionEnum } from "./ProjectionEnum.js"; import { Utils } from "./Utils"; @@ -60,8 +59,8 @@ export let View = (function () { // Add a reference to the WebGL API this.options = aladin.options; this.aladinDiv = this.aladin.aladinDiv; - this.popup = new Popup(this.aladinDiv, this); this.createCanvases(); + this.loadingState = false; let self = this; @@ -228,10 +227,13 @@ export let View = (function () { self.fixLayoutDimensions(); }) } else {*/ - - this.resizeObserver = new ResizeObserver(() => { + let resizeLayout = () => { self.fixLayoutDimensions(); - //self.requestRedraw(); + } + let doit; + this.resizeObserver = new ResizeObserver(() => { + clearTimeout(doit); + doit = setTimeout(resizeLayout, 100); }); self.resizeObserver.observe(this.aladinDiv); @@ -331,7 +333,7 @@ export let View = (function () { canvas.className = name; // Append the canvas to the aladinDiv - this.aladinDiv.appendChild(canvas); + this.aladinDiv.appendChild(canvas, 'begin'); return canvas; }; @@ -382,15 +384,18 @@ export let View = (function () { if (!this.logoDiv) { this.logoDiv = this.aladinDiv.querySelector('.aladin-logo'); } - if (this.width > 800) { - this.logoDiv.classList.remove('aladin-logo-small'); - this.logoDiv.classList.add('aladin-logo-large'); - this.logoDiv.style.width = '90px'; - } - else { - this.logoDiv.classList.add('aladin-logo-small'); - this.logoDiv.classList.remove('aladin-logo-large'); - this.logoDiv.style.width = '32px'; + + if (this.logoDiv) { + if (this.width > 800) { + this.logoDiv.classList.remove('aladin-logo-small'); + this.logoDiv.classList.add('aladin-logo-large'); + this.logoDiv.style.width = '90px'; + } + else { + this.logoDiv.classList.add('aladin-logo-small'); + this.logoDiv.classList.remove('aladin-logo-large'); + this.logoDiv.style.width = '32px'; + } } this.computeNorder(); @@ -413,7 +418,7 @@ export let View = (function () { View.prototype.setMode = function (mode) { this.mode = mode; if (this.mode == View.TOOL_SIMBAD_POINTER) { - this.popup.hide(); + this.aladin.popup.hide(); this.catalogCanvas.style.cursor = ''; this.catalogCanvas.classList.add('aladin-sp-cursor'); } @@ -715,10 +720,10 @@ export let View = (function () { // footprint selection code adapted from Fabrizio Giordano dev. from Serco for ESA/ESDC if (o.marker) { // could be factorized in Source.actionClicked - view.popup.setTitle(o.popupTitle); - view.popup.setText(o.popupDesc); - view.popup.setSource(o); - view.popup.show(); + view.aladin.popup.setTitle(o.popupTitle); + view.aladin.popup.setText(o.popupDesc); + view.aladin.popup.setSource(o); + view.aladin.popup.show(); } else { if (view.lastClickedObject) { @@ -750,7 +755,7 @@ export let View = (function () { if (view.lastClickedObject) { //view.aladin.measurementTable.hide(); //view.aladin.sodaForm.hide(); - view.popup.hide(); + view.aladin.popup.hide(); // Deselect the last clicked object if (view.lastClickedObject instanceof Ellipse || view.lastClickedObject instanceof Circle || view.lastClickedObject instanceof Polyline) { @@ -792,7 +797,7 @@ export let View = (function () { var lastMouseMovePos = null; Utils.on(view.catalogCanvas, "mousemove touchmove", function (e) { e.preventDefault(); - e.stopPropagation(); + //e.stopPropagation(); const xymouse = Utils.relMouseCoords(e); @@ -1683,12 +1688,13 @@ export let View = (function () { }; View.prototype.setProjection = function (projName) { - if (this.projection.id === ProjectionEnum[projName].id) { - return; + if (!ProjectionEnum[projName]) { + console.warn(projName + " is not a valid projection.") + projName = 'SIN' } - if (!ProjectionEnum[projName]) { - throw projName + " is not a valid projection." + if (this.projection.id === ProjectionEnum[projName].id) { + return; } this.projection = ProjectionEnum[projName]; diff --git a/src/js/gui/Box/CatalogQueryBox.js b/src/js/gui/Box/CatalogQueryBox.js index 99e361d9..25f4a087 100644 --- a/src/js/gui/Box/CatalogQueryBox.js +++ b/src/js/gui/Box/CatalogQueryBox.js @@ -95,16 +95,17 @@ import { ContextMenu } from "../Widgets/ContextMenu.js"; let self; let loadBtn = new CtxMenuActionButtonOpener({ + openDirection: "left", content: 'Load', disable: true, }, aladin) - super({ + super(aladin, { position, content: Layout.horizontal({ layout: [catNameTextInput, loadBtn] }) - }, aladin.aladinDiv) + }) this.addClass('aladin-box-night') @@ -236,25 +237,37 @@ import { ContextMenu } from "../Widgets/ContextMenu.js"; } }) box._show(); + + self._hide(); } }) } if (item && item.hips_service_url) { layout.push({ - label: 'Progressive catalogue', + label: 'HiPS catalogue', disable: !item.hips_service_url, action(o) { self.fnIdSelected('hips', { hipsURL: item.hips_service_url, id: item.ID, }) + + self._hide(); } }) } this.loadBtn.update({ctxMenu: layout, disable: false}, aladin) } + _hide() { + if (this.loadBtn) { + this.loadBtn._hide(); + } + + super._hide() + } + static layerSelector = undefined; static getInstance(aladin, position) { diff --git a/src/js/gui/Box/ConeSearchBox.js b/src/js/gui/Box/ConeSearchBox.js index 11dc8840..1e22ec29 100644 --- a/src/js/gui/Box/ConeSearchBox.js +++ b/src/js/gui/Box/ConeSearchBox.js @@ -140,15 +140,18 @@ import { Angle } from "../../libs/astro/angle.js"; ] }); - super({ - header: { - draggable: true, - title: 'Cone Search box' - }, - content: Layout.horizontal({ - layout: [form] - }) - }, aladin.aladinDiv) + super( + aladin, + { + header: { + draggable: true, + title: 'Cone Search box' + }, + content: Layout.horizontal({ + layout: [form] + }) + } + ) // hide by default //console.log("hide cone search") diff --git a/src/js/gui/Box/GotoBox.js b/src/js/gui/Box/GotoBox.js index 301d6465..4d27040c 100644 --- a/src/js/gui/Box/GotoBox.js +++ b/src/js/gui/Box/GotoBox.js @@ -77,14 +77,17 @@ export class GotoBox extends Box { } }); - super({content: textField}, aladin.aladinDiv) + super(aladin, {content: textField}) this.addClass('aladin-box-night'); this.textField = textField; } _hide() { - this.textField.set('') + if (this.textField) { + this.textField.set('') + } + super._hide() } diff --git a/src/js/gui/Box/GridBox.js b/src/js/gui/Box/GridBox.js index 6c5ce854..f7ed3287 100644 --- a/src/js/gui/Box/GridBox.js +++ b/src/js/gui/Box/GridBox.js @@ -173,13 +173,17 @@ export class GridBox extends Box { colorInput.set(hexColor) }); - super({ - content: layout, - }, aladin.aladinDiv) + super(aladin, + { + content: layout, + } + ) this.addClass("aladin-box-night") this.aladin = aladin; + + this._hide(); } _hide() { diff --git a/src/js/gui/Box/HiPSSelectorBox.js b/src/js/gui/Box/HiPSSelectorBox.js index 8fb3e075..c0eb8c6f 100644 --- a/src/js/gui/Box/HiPSSelectorBox.js +++ b/src/js/gui/Box/HiPSSelectorBox.js @@ -37,33 +37,13 @@ import { Utils } from "../../Utils.ts"; *****************************************************************************/ export class HiPSSelectorBox extends Box { - - constructor(options, aladin) { - let layer = options.layer; - let fnIdSelected = (IDOrURL) => { - let name; - - if (layer) { - name = layer; - } else { - name = Utils.uuidv4(); - } - - aladin.setOverlayImageLayer(IDOrURL, name); - }; - + constructor(options, callback, aladin) { let inputText = Input.text({ - //tooltip: {content: 'Search for a VizieR catalogue', position: {direction :'bottom'}}, label: "Survey", name: 'autocomplete', type: 'text', placeholder: "Type ID, title, keyword or URL", autocomplete: 'off', - /*change(e) { - loadBtn.update({disable: true}) - // Unfocus the keyboard on android devices (maybe it concerns all smartphones) when the user click on enter - //inputText.element().blur(); - }*/ }); let self; @@ -71,22 +51,25 @@ import { Utils } from "../../Utils.ts"; content: 'Load', disable: true, action(e) { - fnIdSelected && fnIdSelected(inputText.get()); + callback && callback(inputText.get()); // reset the field inputText.set(''); self._hide(); } }) - super({ - ...options, - content: Layout.horizontal({ - layout: [ - inputText, - loadBtn - ] - }) - }, aladin.aladinDiv) + super( + aladin, + { + ...options, + content: Layout.horizontal({ + layout: [ + inputText, + loadBtn + ] + }) + } + ) this.addClass('aladin-box-night') @@ -146,7 +129,6 @@ import { Utils } from "../../Utils.ts"; inputText.set(item.ID); loadBtn.update({disable: false}); - //self.fnIdSelected && self.fnIdSelected(item.ID); inputText.element().blur(); }, // attach container to AL div if needed (to prevent it from being hidden in full screen mode) diff --git a/src/js/gui/Box/ServiceQueryBox.js b/src/js/gui/Box/ServiceQueryBox.js index 5569c899..5107f621 100644 --- a/src/js/gui/Box/ServiceQueryBox.js +++ b/src/js/gui/Box/ServiceQueryBox.js @@ -97,13 +97,16 @@ export class ServiceQueryBox extends Box { subInputs: [] }); - super({ - header: { - draggable: true, - title: 'Service query' - }, - content: form - }, aladin.aladinDiv) + super( + aladin, + { + header: { + draggable: true, + title: 'Service query' + }, + content: form + } + ) this.form = form; this.aladin = aladin; diff --git a/src/js/gui/Box/ShortLivedBox.js b/src/js/gui/Box/ShortLivedBox.js index e7a04488..d7d14946 100644 --- a/src/js/gui/Box/ShortLivedBox.js +++ b/src/js/gui/Box/ShortLivedBox.js @@ -33,12 +33,17 @@ import { Box } from "../Widgets/Box.js"; export class ShortLivedBox extends Box { // Constructor constructor(aladin) { - super({cssStyle: { - color: 'white', - backgroundColor: 'black', - borderRadius: '3px', - padding: 0, - }}, aladin.aladinDiv) + super( + aladin, + { + cssStyle: { + color: 'white', + backgroundColor: 'black', + borderRadius: '3px', + padding: 0, + } + } + ) } _show(options) { diff --git a/src/js/gui/Box/StatusBarBox.js b/src/js/gui/Box/StatusBarBox.js index f6d9c7a1..65b8d00c 100644 --- a/src/js/gui/Box/StatusBarBox.js +++ b/src/js/gui/Box/StatusBarBox.js @@ -38,14 +38,17 @@ import infoIconUrl from '../../../../assets/icons/info.svg'; export class StatusBarBox extends Box { constructor(aladin) { - super({ - cssStyle: { - color: 'white', - backgroundColor: 'black', - borderRadius: '3px', - padding: 0, + super( + aladin, + { + cssStyle: { + color: 'white', + backgroundColor: 'black', + borderRadius: '3px', + padding: 0, + } } - }, aladin.aladinDiv) + ) this.addClass("aladin-status-bar"); @@ -128,8 +131,6 @@ export class StatusBarBox extends Box { message.addClass("aladin-status-bar-message") - console.log(message) - this._show({ content: [StatusBarBox.icons[task.type], message], position: { diff --git a/src/js/gui/Box/SurveyEditBox.js b/src/js/gui/Box/SurveyEditBox.js index 44fc15b3..a7fd5eb2 100644 --- a/src/js/gui/Box/SurveyEditBox.js +++ b/src/js/gui/Box/SurveyEditBox.js @@ -44,13 +44,16 @@ import { CmapSelector } from "../Selector/Colormap.js"; export class LayerEditBox extends Box { // Constructor constructor(aladin, options) { - super({ - cssStyle: { - padding: '4px', - backgroundColor: 'black', - }, - ...options - }, aladin.aladinDiv) + super( + aladin, + { + cssStyle: { + padding: '4px', + backgroundColor: 'black', + }, + ...options + } + ) this.aladin = aladin; @@ -149,10 +152,8 @@ import { CmapSelector } from "../Selector/Colormap.js"; sqrt: { content: 'sqrt', cssStyle: { - width: '18px', height: '18px', padding: 0, - width: '3em', color: 'black' }, change(e) { @@ -163,10 +164,8 @@ import { CmapSelector } from "../Selector/Colormap.js"; linear: { content: 'linear', cssStyle: { - width: '18px', height: '18px', padding: 0, - width: '3em', color: 'black' }, @@ -178,10 +177,8 @@ import { CmapSelector } from "../Selector/Colormap.js"; asinh: { content: 'asinh', cssStyle: { - width: '18px', height: '18px', padding: 0, - width: '3em', color: 'black' }, @@ -193,10 +190,8 @@ import { CmapSelector } from "../Selector/Colormap.js"; pow2: { content: 'pow2', cssStyle: { - width: '18px', height: '18px', padding: 0, - width: '3em', color: 'black' }, @@ -208,10 +203,8 @@ import { CmapSelector } from "../Selector/Colormap.js"; log: { content: 'log', cssStyle: { - width: '18px', height: '18px', padding: 0, - width: '3em', color: 'black' }, @@ -237,7 +230,7 @@ import { CmapSelector } from "../Selector/Colormap.js"; self.opacitySettingsContent = Layout.horizontal({ layout: [ Input.slider({ - tooltip: {content: layerOpacity, position: {direction: 'right'}}, + tooltip: {content: layerOpacity, position: {direction: 'bottom'}}, name: 'opacitySlider', type: 'range', min: 0.0, @@ -247,7 +240,7 @@ import { CmapSelector } from "../Selector/Colormap.js"; const opacity = +e.target.value layer.setOpacity(opacity) - slider.update({tooltip: {content: opacity.toFixed(2), position: {direction: 'right'}}}) + slider.update({tooltip: {content: opacity.toFixed(2), position: {direction: 'bottom'}}}) } }), ] diff --git a/src/js/gui/Button/CtxMenuOpener.js b/src/js/gui/Button/CtxMenuOpener.js index 43ed3f86..1bed047f 100644 --- a/src/js/gui/Button/CtxMenuOpener.js +++ b/src/js/gui/Button/CtxMenuOpener.js @@ -40,11 +40,13 @@ import { ContextMenu } from "../Widgets/ContextMenu.js"; } */ export class CtxMenuActionButtonOpener extends ActionButton { + //static BUTTONS = []; + // Constructor constructor(options, aladin) { let self; - let ctxMenu = ContextMenu.getInstance(aladin) + let ctxMenu = new ContextMenu(aladin, {hideOnClick: false}) super({ ...options, cssStyle: { @@ -58,25 +60,39 @@ export class CtxMenuActionButtonOpener extends ActionButton { } self.ctxMenu._hide(); - self.ctxMenu.attach(self.layout) - self.ctxMenu.show({ - position: { - nextTo: self, - direction: options.openDirection || 'bottom', - }, - cssStyle: options.ctxMenu && options.ctxMenu.cssStyle - }); + + if (self.hidden === true) { + self.ctxMenu.attach(self.layout) + self.ctxMenu.show({ + position: { + nextTo: self, + direction: options.openDirection || 'bottom', + }, + cssStyle: options.ctxMenu && options.ctxMenu.cssStyle + }); + + //CtxMenuActionButtonOpener.BUTTONS.forEach(b => {b.hidden = true}) + } + + self.hidden = !self.hidden; } }) + this.hidden = true; + this.layout = options.ctxMenu; self = this; self.ctxMenu = ctxMenu; + + //CtxMenuActionButtonOpener.BUTTONS.push(this); } - hideCtxMenu() { + _hide() { this.ctxMenu._hide(); + this.hidden = true; + + super._hide(); } update(options) { @@ -85,5 +101,16 @@ export class CtxMenuActionButtonOpener extends ActionButton { } super.update(options) + + if (!this.hidden) { + this.ctxMenu.attach(this.layout) + this.ctxMenu.show({ + position: { + nextTo: this, + direction: options.openDirection || 'bottom', + }, + cssStyle: options.ctxMenu && options.ctxMenu.cssStyle + }); + } } } \ No newline at end of file diff --git a/src/js/gui/Button/MainSurvey.js b/src/js/gui/Button/MainSurvey.js index 3da62e2e..c262af1f 100644 --- a/src/js/gui/Button/MainSurvey.js +++ b/src/js/gui/Button/MainSurvey.js @@ -19,10 +19,8 @@ import { ALEvent } from "../../events/ALEvent"; -import { DOMElement } from "../Widgets/Widget"; - import { ActionButton } from "../Widgets/ActionButton"; -import { SurveyCtxMenu } from "../CtxMenu/SurveyCtxMenu"; +import mapIconUrl from '../../../../assets/icons/map.svg'; /****************************************************************************** * Aladin Lite project @@ -36,10 +34,6 @@ import { SurveyCtxMenu } from "../CtxMenu/SurveyCtxMenu"; * *****************************************************************************/ -/** - * Class representing a Tabs layout - * @extends CtxMenuActionButtonOpener - */ export class MainSurveyActionButton extends ActionButton { /** * UI responsible for displaying the viewport infos @@ -49,15 +43,11 @@ import { SurveyCtxMenu } from "../CtxMenu/SurveyCtxMenu"; super({ ...options, tooltip: {content: 'Survey name
Click to change it!', position: { direction: 'bottom' }}, - content: '
Main survey
', - cssStyle: { - backgroundColor: 'rgba(0, 0, 0, 0.5)', - borderColor: 'white', - color: 'white', - padding: '4px', - }, + iconURL: mapIconUrl, }) + this.addClass('medium-sized-icon') + this._addListeners(aladin) } @@ -67,9 +57,8 @@ import { SurveyCtxMenu } from "../CtxMenu/SurveyCtxMenu"; if (layer.layer === 'base') { let name = (layer.properties && layer.properties.obsTitle) || layer.name; this.update({ - content: '
' + name + '
', tooltip: { - content: name, + content: 'Survey: ' + name, position: { direction: 'left' } diff --git a/src/js/gui/Button/Projection.js b/src/js/gui/Button/Projection.js index a460baad..66a7dfad 100644 --- a/src/js/gui/Button/Projection.js +++ b/src/js/gui/Button/Projection.js @@ -18,8 +18,7 @@ // import { CtxMenuActionButtonOpener } from "./CtxMenuOpener"; -import { ContextMenu } from "../Widgets/ContextMenu"; -import projectionSvg from '../../../../assets/icons/grid.svg'; +import projectionSvg from '../../../../assets/icons/projection.svg'; import { ProjectionEnum } from "../../ProjectionEnum"; /****************************************************************************** * Aladin Lite project @@ -51,6 +50,7 @@ import { ProjectionEnum } from "../../ProjectionEnum"; borderColor: '#484848', cursor: 'pointer', }, + openDirection: 'bottom', /*action(o) { ctxMenu.attach(layout); }*/ diff --git a/src/js/gui/Button/ShareView.js b/src/js/gui/Button/ShareView.js index 22e1e4d4..e888589c 100644 --- a/src/js/gui/Button/ShareView.js +++ b/src/js/gui/Button/ShareView.js @@ -112,7 +112,7 @@ import shareIconUrl from '../../../../assets/icons/share.svg'; iconURL: shareIconUrl, openDirection: 'top', tooltip: {content: 'You can share/export your view into many ways', position: {direction: 'top'}}, - }); + }, aladin); self = this; this.addClass('medium-sized-icon') } diff --git a/src/js/gui/CtxMenu/OverlayStack.js b/src/js/gui/CtxMenu/OverlayStack.js index 554ffac4..c897e272 100644 --- a/src/js/gui/CtxMenu/OverlayStack.js +++ b/src/js/gui/CtxMenu/OverlayStack.js @@ -50,12 +50,11 @@ export class OverlayStack extends ContextMenu { /*window.addEventListener("resize", (e) => { this._hide(); })*/ - let self = this; - document.addEventListener('click', (e) => { + /*document.addEventListener('click', (e) => { if (!self.el.contains(e.target) && this.mode === 'stack') { this._hide() } - }); + });*/ this._addListeners(); } @@ -122,9 +121,8 @@ export class OverlayStack extends ContextMenu { //o.preventDefault(); self._hide(); - - let catBox = CatalogQueryBox.getInstance(self.aladin, self.position); - catBox._show(); + self.catBox = new CatalogQueryBox(self.aladin, self.position); + self.catBox._show(); self.mode = 'search'; } @@ -237,7 +235,7 @@ export class OverlayStack extends ContextMenu { height: 'fit-content', }; let showBtn = ActionButton.createIconBtn({ - iconURL: showIconUrl, + iconURL: overlay.isShowing ? showIconUrl : hideIconUrl, cssStyle: { backgroundColor: '#bababa', borderColor: '#484848', @@ -248,7 +246,7 @@ export class OverlayStack extends ContextMenu { verticalAlign: 'middle', marginRight: '2px', }, - tooltip: {content: 'Hide', position: {direction: 'bottom'}}, + tooltip: {content: overlay.isShowing ? 'Hide' : 'Show', position: {direction: 'bottom'}}, action(e, btn) { if (overlay.isShowing) { overlay.hide() @@ -356,7 +354,6 @@ export class OverlayStack extends ContextMenu { ...options, ...{position: this.position}, cssStyle: { - color: 'white', backgroundColor: 'black', maxWidth: '20em', //border: '1px solid white', @@ -367,10 +364,16 @@ export class OverlayStack extends ContextMenu { _hide() { this.mode = 'stack'; - if (this.position) { - let catBox = CatalogQueryBox.getInstance(this.aladin, this.position); - catBox._hide(); + if (this.catBox) { + this.catBox._hide(); } + + /*let catBox = CatalogQueryBox.getInstance(this.aladin, this.position); + + + if (this.position) { + + }*/ super._hide(); } diff --git a/src/js/gui/CtxMenu/Settings.js b/src/js/gui/CtxMenu/Settings.js index 285f477b..fab4e232 100644 --- a/src/js/gui/CtxMenu/Settings.js +++ b/src/js/gui/CtxMenu/Settings.js @@ -151,7 +151,7 @@ export class SettingsCtxMenu extends ContextMenu { this.attach([ { label: { - content: [self.backgroundColorInput, 'Background color'] + content: [self.backgroundColorInput, 'Back color'] }, mustHide: false, action(o) {} @@ -161,7 +161,7 @@ export class SettingsCtxMenu extends ContextMenu { subMenu: [ { label: { - content: [self.reticleCheckbox, 'Reticle'] + content: [self.reticleCheckbox, 'Show/Hide'] }, action(o) { let newVal = self.toggleCheckbox(self.reticleCheckbox); @@ -306,7 +306,6 @@ export class SettingsCtxMenu extends ContextMenu { super.show({ position: this.position, cssStyle: { - color: 'white', backgroundColor: 'black', maxWidth: '20em', } diff --git a/src/js/gui/CtxMenu/SurveyCtxMenu.js b/src/js/gui/CtxMenu/SurveyCtxMenu.js deleted file mode 100644 index 343d5994..00000000 --- a/src/js/gui/CtxMenu/SurveyCtxMenu.js +++ /dev/null @@ -1,144 +0,0 @@ -import { ImageLayer } from "../../ImageLayer.js"; -import searchIconImg from '../../../../assets/icons/search.svg'; - -import { ContextMenu } from "../Widgets/ContextMenu"; -import { HiPSSelectorBox } from "../Box/HiPSSelectorBox"; - -export class SurveyCtxMenu extends ContextMenu { - // Constructor - constructor(aladin) { - super(aladin) - - let layout = [{ - 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) { - if (!self.hipsBox) { - self.hipsBox = new HiPSSelectorBox({ - layer: 'base', - position: self.position, - }, - aladin - ); - } - - self.hipsBox._show() - } - }]; - - let layers = ImageLayer.LAYERS.sort(function (a, b) { - if (!a.order) { - return a.name > b.name ? 1 : -1; - } - return a.maxOrder && a.maxOrder > b.maxOrder ? 1 : -1; - }); - - for(let layer of layers) { - let backgroundUrl = SurveyCtxMenu.previewImagesUrl[layer.name]; - let cssStyle = { - height: '2.5em', - }; - if (backgroundUrl) { - cssStyle = { - backgroundSize: '100%', - backgroundImage: 'url(' + backgroundUrl + ')', - ...cssStyle - } - } - - layout.push({ - //selected: layer.name === aladin.getBaseImageLayer().name, - label: '
' + layer.name + '
', - cssStyle: cssStyle, - action(e) { - let cfg = ImageLayer.LAYERS.find((l) => l.name === layer.name); - let newLayer; - - // Max order is specific for surveys - if (cfg.subtype === "fits") { - // FITS - newLayer = self.aladin.createImageFITS( - cfg.url, - cfg.name, - cfg.options, - ); - } else { - // HiPS - newLayer = self.aladin.createImageSurvey( - cfg.id, - cfg.name, - cfg.url, - undefined, - cfg.maxOrder, - cfg.options - ); - } - - self.aladin.setOverlayImageLayer(newLayer, 'base'); - - if (self.hipsBox) { - self.hipsBox._hide(); - } - } - }) - } - - let self = this; - self.hipsSelector = null; - this.attach(layout) - } - - _show(options) { - // set the position when we want to show - if (options && options.position) { - this.position = options.position; - } - - console.log(this.aladin.aladinDiv.offsetHeight) - let maxHeight = Math.min(this.aladin.aladinDiv.offsetHeight, 500); - super.show({ - position: this.position, - cssStyle: { - width: '20em', - overflowY: 'scroll', - maxHeight: maxHeight + 'px', - color: 'white', - backgroundColor: 'black', - } - }) - } - - 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', - 'Halpha': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_VTSS_Ha.jpg', - 'IRAC color I1,I2,I4 - (GLIMPSE, SAGE, SAGE-SMC, SINGS)': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_SPITZER_color.jpg', - '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', - 'VTSS-Ha': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_Finkbeiner.jpg', - 'XMM PN colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_XMM_PN_color.jpg', - 'SDSS9 colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_SDSS9_color.jpg', - }; -} \ No newline at end of file diff --git a/src/js/gui/CtxMenu/SurveyStack.js b/src/js/gui/CtxMenu/SurveyStack.js index ada38cbd..d78d5ea5 100644 --- a/src/js/gui/CtxMenu/SurveyStack.js +++ b/src/js/gui/CtxMenu/SurveyStack.js @@ -41,28 +41,32 @@ import editIconUrl from '../../../../assets/icons/edit.svg'; import { ImageFITS } from "../../ImageFITS.js"; import { LayerEditBox } from "../Box/SurveyEditBox.js"; import { Utils } from "../../Utils.ts"; +import { ImageLayer } from "../../ImageLayer.js"; +import searchIconImg from '../../../../assets/icons/search.svg'; + 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', - 'DSS2/color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_DSS2_color.jpg', - 'DSS2/red': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_DSS2_red.jpg', - 'Fermi/color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_Fermi_color.jpg', - 'GALEXGR6/AIS/NUV': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_GALEXGR6_7_color.jpg', + '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', - 'VTSS/Ha': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_VTSS_Ha.jpg', - 'SPITZER/color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_SPITZER_color.jpg', - 'IRIS/color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_IRIS_color.jpg', - 'Mellinger/color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_Mellinger_color.jpg', - 'PanSTARRS/DR1/color-i-r-g': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_PanSTARRS_DR1_color-z-zg-g.jpg', - 'PanSTARRS/DR1/color-z-zg-g': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_PanSTARRS_DR1_color-z-zg-g.jpg', - '2MASS/color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_2MASS_color.jpg', - 'AKARI/FIS/Color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_AKARI_FIS_Color.jpg', - 'SWIFT_BAT_FLUX': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_SWIFT_BAT_FLUX.jpg', - 'Finkbeiner': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_Finkbeiner.jpg', - 'XMM/PN/color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_XMM_PN_color.jpg', - 'SDSS9/color': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_SDSS9_color.jpg', + 'Halpha': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_VTSS_Ha.jpg', + 'IRAC color I1,I2,I4 - (GLIMPSE, SAGE, SAGE-SMC, SINGS)': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_SPITZER_color.jpg', + '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', + 'VTSS-Ha': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_Finkbeiner.jpg', + 'XMM PN colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_XMM_PN_color.jpg', + 'SDSS9 colored': 'https://aladin.cds.unistra.fr/AladinLite/survey-previews/P_SDSS9_color.jpg', }; // Constructor @@ -76,12 +80,11 @@ export class Stack extends ContextMenu { this._hide(); })*/ - let self = this; - document.addEventListener('click', e => { + /*document.addEventListener('click', e => { if (!self.el.contains(e.target) && this.mode === 'stack') { this._hide() } - }); + });*/ this.mode = 'stack'; this._addListeners(); @@ -151,9 +154,18 @@ export class Stack extends ContextMenu { self._hide(); self.hipsSelectorBox = new HiPSSelectorBox({ - position: self.position, - layer: Utils.uuidv4(), - }, self.aladin); + position: self.position, + }, + (HiPSId) => { + let name = Utils.uuidv4() + self.aladin.setOverlayImageLayer(HiPSId, name) + + self.mode = 'stack'; + self._show(); + }, + self.aladin + ); + self.hipsSelectorBox._show(); self.mode = 'hips'; @@ -161,6 +173,7 @@ export class Stack extends ContextMenu { }, ContextMenu.fileLoaderItem({ label: 'FITS image file', + accept: '.fits', action(file) { let url = URL.createObjectURL(file); @@ -188,6 +201,7 @@ export class Stack extends ContextMenu { for(const layer of layers) { const name = layer.name; + let backgroundUrl = this._findPreviewImageUrl(layer); let cssStyle = { height: 'fit-content', @@ -202,7 +216,7 @@ export class Stack extends ContextMenu { } let showBtn = ActionButton.createIconBtn({ - iconURL: showIconUrl, + iconURL: layer.getOpacity() === 0.0 ? hideIconUrl : showIconUrl, cssStyle: { backgroundColor: '#bababa', borderColor: '#484848', @@ -213,8 +227,11 @@ export class Stack extends ContextMenu { verticalAlign: 'middle', marginRight: '2px', }, - tooltip: {content: 'Hide', position: {direction: 'bottom'}}, + tooltip: {content: layer.getOpacity() === 0.0 ? 'Show' : 'Hide', position: {direction: 'bottom'}}, action(e, btn) { + e.preventDefault(); + e.stopPropagation(); + let opacity = layer.getOpacity(); if (opacity === 0.0) { layer.setOpacity(1.0); @@ -273,9 +290,11 @@ export class Stack extends ContextMenu { } }); + let layerClassName = 'a' + layer.layer.replace(/[.\/ ]/g, '') + let item = Layout.horizontal({ layout: [ - '
' + name + '
', + '
' + name + '
', Layout.horizontal({layout: [showBtn, editBtn, deleteBtn]}) ], cssStyle: { @@ -290,26 +309,119 @@ export class Stack extends ContextMenu { let l = { label: item, cssStyle, - action(o) { - self.aladin.selectLayer(layer.layer); - // recompute the stack - self.attach({layers}) - self._show() - } - }; - - if (!Utils.hasTouchScreen()) { - l.hover = (e) => { + hover(e) { showBtn.el.style.visibility = 'visible' editBtn.el.style.visibility = 'visible' deleteBtn.el.style.visibility = 'visible' - } - - l.unhover = (e) => { + }, + unhover(e) { showBtn.el.style.visibility = 'hidden' editBtn.el.style.visibility = 'hidden' deleteBtn.el.style.visibility = 'hidden' } + }; + + 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 = new HiPSSelectorBox({ + position: self.position, + }, + (HiPSId) => { + self.aladin.setOverlayImageLayer(HiPSId, 'base'); + self.mode = 'stack'; + self._show(); + }, + self.aladin + ); + + self.hipsBox._show() + + self.mode = 'hips'; + } + }]; + + let layers = ImageLayer.LAYERS.sort(function (a, b) { + if (!a.order) { + return a.name > b.name ? 1 : -1; + } + return a.maxOrder && a.maxOrder > b.maxOrder ? 1 : -1; + }); + + for(let layer of layers) { + let backgroundUrl = Stack.previewImagesUrl[layer.name]; + let cssStyle = { + height: '2.5em', + }; + if (backgroundUrl) { + cssStyle = { + backgroundSize: '100%', + backgroundImage: 'url(' + backgroundUrl + ')', + ...cssStyle + } + } + + l.subMenu.push({ + //selected: layer.name === aladin.getBaseImageLayer().name, + label: '
' + layer.name + '
', + cssStyle: cssStyle, + action(e) { + let cfg = ImageLayer.LAYERS.find((l) => l.name === layer.name); + let newLayer; + + // Max order is specific for surveys + if (cfg.subtype === "fits") { + // FITS + newLayer = self.aladin.createImageFITS( + cfg.url, + cfg.name, + cfg.options, + ); + } else { + // HiPS + newLayer = self.aladin.createImageSurvey( + cfg.id, + cfg.name, + cfg.url, + undefined, + cfg.maxOrder, + cfg.options + ); + } + + self.aladin.setOverlayImageLayer(newLayer, 'base'); + //self._hide(); + }, + hover(e, item) { + item.style.filter = 'brightness(1.5)'; + }, + unhover(e, item) { + item.style.filter = 'brightness(1.0)'; + } + }) + } + } + + l.action = (o) => { + let oldLayerClassName = 'a' + self.aladin.getSelectedLayer().replace(/[.\/ ]/g, '') + self.el.querySelector('.' + oldLayerClassName).style.removeProperty('border') + self.aladin.selectLayer(layer.layer); + self.el.querySelector('.' + layerClassName).style.border = '1px solid white'; } layout.push(l); @@ -342,11 +454,16 @@ export class Stack extends ContextMenu { super.show({ position: this.position, cssStyle: { - width: '15em', - color: 'white', + maxWidth: '15em', backgroundColor: 'black', } }) + + let subMenus = this.element().querySelectorAll(".aladin-context-sub-menu"); + + let defaultHiPSMenu = subMenus[subMenus.length - 1]; + defaultHiPSMenu.style.maxHeight = Math.min(500, this.aladin.aladinDiv.offsetHeight) + 'px'; + defaultHiPSMenu.style.overflowY = 'scroll'; } _hide() { diff --git a/src/js/gui/FoV.js b/src/js/gui/FoV.js index 8312a9ee..a568de8e 100644 --- a/src/js/gui/FoV.js +++ b/src/js/gui/FoV.js @@ -27,33 +27,33 @@ * Author: Thomas Boch[CDS] * *****************************************************************************/ - - -import { Numbers } from "../libs/astro/coo.js"; +import { Numbers } from "../libs/astro/coo.js"; import { Layout } from "./Layout.js"; import { DOMElement } from "./Widgets/Widget.js"; import { ALEvent } from "../events/ALEvent.js"; +import { Utils } from "../Utils"; export class FoV extends DOMElement { // constructor constructor(aladin) { let el = Layout.horizontal({ - layout: [ + layout: ['FoV: ', '
', '
×
', '
', - ], - tooltip: { - content: 'Field of View in ra and dec direction', - position: { direction: 'bottom' }, - } + ] }); el.addClass('aladin-fov'); 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(); @@ -94,6 +94,5 @@ export class FoV extends DOMElement { return Numbers.toDecimal(fov, 1) + suffix; } - }; diff --git a/src/js/gui/Layout.js b/src/js/gui/Layout.js index 6677cb6a..937cc055 100644 --- a/src/js/gui/Layout.js +++ b/src/js/gui/Layout.js @@ -79,8 +79,12 @@ export class Layout extends DOMElement { this.setPosition(options.position) } - if (options.direction) { - this.addClass(options.direction === 'horizontal' ? this.addClass('aladin-horizontal-list') : this.addClass('aladin-vertical-list')) + if (options.orientation) { + if (options.orientation === 'horizontal') { + this.addClass('aladin-horizontal-list') + } else { + this.addClass('aladin-vertical-list') + } } else { this.addClass('aladin-horizontal-list') } @@ -180,6 +184,11 @@ export class Layout extends DOMElement { } } + if (this.options.position) { + this.setPosition(this.options.position) + } + + //super._show() // attach to the DOM again //this.attachTo(this.target); } diff --git a/src/js/gui/Location.js b/src/js/gui/Location.js index c3948adc..1e4087f1 100644 --- a/src/js/gui/Location.js +++ b/src/js/gui/Location.js @@ -38,6 +38,7 @@ import copyIconBtn from '../../../assets/icons/copy.svg'; import { ALEvent } from "../events/ALEvent.js"; import { Layout } from "./Layout.js"; import { ActionButton } from "./Widgets/ActionButton.js"; +import { Utils } from "../Utils"; export class Location extends DOMElement { // constructor @@ -57,7 +58,7 @@ export class Location extends DOMElement { self.copyCoordinatesToClipboard() } }), - '
' + '
' ] }) el.addClass('aladin-location'); @@ -109,12 +110,26 @@ export class Location extends DOMElement { }); this.aladin = aladin; + + let [lon, lat] = aladin.wasm.getCenter(); + this.update({ + lon: lon, + lat: lat, + isViewCenter: true, + frame: aladin.view.cooFrame + }, aladin) + + if (Utils.hasTouchScreen()) { + this.el.style.padding = "0.2em"; + } }; + static prec = 7; + update(options, aladin) { let self = this; const updateFromLonLatFunc = (lon, lat, cooFrame) => { - var coo = new Coo(lon, lat, 7); + var coo = new Coo(lon, lat, Location.prec); let textEl = self.el.querySelector('.aladin-monospace-text') if (cooFrame == CooFrameEnum.J2000) { textEl.innerHTML = coo.format('s/'); diff --git a/src/js/gui/Toolbar/Menu.js b/src/js/gui/Toolbar/Menu.js index c0ad6d24..ba702157 100644 --- a/src/js/gui/Toolbar/Menu.js +++ b/src/js/gui/Toolbar/Menu.js @@ -51,8 +51,7 @@ import { Utils } from "../Utils"; * *****************************************************************************/ import { Toolbar } from "../Widgets/Toolbar"; -import { SurveyCtxMenu } from "../CtxMenu/SurveyCtxMenu"; -import { MainSurveyActionButton } from "../Button/MainSurvey"; + /** * Class representing a Tabs layout * @extends DOMElement @@ -85,43 +84,44 @@ import { MainSurveyActionButton } from "../Button/MainSurvey"; } // 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 + }; + this.indices = []; + + this.aladin = aladin; + + this._initControls(); + } + + _initControls() { + let self = this; + let aladin = this.aladin; this.controls = { - survey: new MainSurveyActionButton( - aladin, - { - action(o) { - let toolWasShown = !survey.isHidden; - - self.closeAll(); - - if (!toolWasShown) { - survey._show({ - position: { - nextTo: self.controls['survey'], - direction: options.direction === 'horizontal' ? 'bottom' : 'left', - } - }); - } - } - } - ), stack: ActionButton.createIconBtn({ iconURL: stackImageIconUrl, tooltip: { content: 'Open the stack layer menu', - position: { direction: 'left'}, + position: { direction: self.options.direction === 'right' ? 'left' : 'right' }, }, action(o) { - let toolWasShown = !stack.isHidden; + let toolWasShown = !self.panels["stack"].isHidden; self.closeAll(); if (!toolWasShown) { - stack._show({ + self.panels["stack"]._show({ position: { nextTo: self.controls['stack'], - direction: options.direction === 'horizontal' ? 'bottom' : 'left', + direction: self.options.direction === 'right' ? 'left' : 'right', } }); } @@ -131,18 +131,18 @@ import { MainSurveyActionButton } from "../Button/MainSurvey"; iconURL: stackOverlayIconUrl, tooltip: { content: 'Open the overlays menu', - position: { direction: 'left'}, + position: { direction: self.options.direction === 'right' ? 'left' : 'right'}, }, action(o) { - let toolWasShown = !overlay.isHidden; + let toolWasShown = !self.panels["overlay"].isHidden; self.closeAll(); if (!toolWasShown) { - overlay._show({ + self.panels["overlay"]._show({ position: { nextTo: self.controls['overlay'], - direction: options.direction === 'horizontal' ? 'bottom' : 'left', + direction: self.options.direction === 'right' ? 'left' : 'right', } }); } @@ -153,18 +153,18 @@ import { MainSurveyActionButton } from "../Button/MainSurvey"; iconURL: searchIcon, tooltip: { content: 'Search for where a celestial object is', - position: { direction: 'left'}, + position: { direction: self.options.direction === 'right' ? 'left' : 'right'}, }, action(o) { - let toolWasShown = !goto.isHidden; + let toolWasShown = !self.panels["goto"].isHidden; self.closeAll(); if (!toolWasShown) { - goto._show({ + self.panels["goto"]._show({ position: { nextTo: self.controls['goto'], - direction: options.direction === 'horizontal' ? 'bottom' : 'left', + direction: self.options.direction === 'right' ? 'left' : 'right', } }); } @@ -174,18 +174,18 @@ import { MainSurveyActionButton } from "../Button/MainSurvey"; iconURL: gridIcon, tooltip: { content: 'Open the grid layer menu', - position: { direction: 'left'}, + position: { direction: self.options.direction === 'right' ? 'left' : 'right'}, }, action(o) { - let toolWasShown = !grid.isHidden; + let toolWasShown = !self.panels["grid"].isHidden; self.closeAll(); if (!toolWasShown) { - grid._show({ + self.panels["grid"]._show({ position: { nextTo: self.controls['grid'], - direction: options.direction === 'horizontal' ? 'bottom' : 'left', + direction: self.options.direction === 'right' ? 'left' : 'right', } }); } @@ -195,18 +195,18 @@ import { MainSurveyActionButton } from "../Button/MainSurvey"; iconURL: settingsIcon, tooltip: { content: 'Some general settings e.g. background color, reticle, windows to show', - position: { direction: 'left' }, + position: { direction: self.options.direction === 'right' ? 'left' : 'right' }, }, action(o) { - let toolWasShown = !settings.isHidden; + let toolWasShown = !self.panels["settings"].isHidden; self.closeAll(); if (!toolWasShown) { - settings._show({ + self.panels["settings"]._show({ position: { nextTo: self.controls["settings"], - direction: options.direction === 'horizontal' ? 'bottom' : 'left', + direction: self.options.direction === 'right' ? 'left' : 'right', } }); } @@ -216,26 +216,30 @@ import { MainSurveyActionButton } from "../Button/MainSurvey"; iconURL: aladin.isInFullscreen ? restoreIcon : maximizeIcon, tooltip: { content: aladin.isInFullscreen ? 'Restore original size' : 'Full-screen', - position: { direction: 'left'}, + position: { direction: self.options.direction === 'right' ? 'left' : 'right'}, }, action(o) { - aladin.toggleFullscreen(aladin.options.realFullscreen); - + 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', - position: { direction: 'left'} + position: { direction: self.options.direction === 'right' ? 'left' : 'right'} } }); } else { + aladin.aladinDiv.style.removeProperty('z-index') + btn.update({ iconURL: maximizeIcon, tooltip: { content: 'Fullscreen', - position: { direction: 'left'} + position: { direction: self.options.direction === 'right' ? 'left' : 'right'} } }); } @@ -245,22 +249,6 @@ import { MainSurveyActionButton } from "../Button/MainSurvey"; } }), }; - - // 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); - let survey = new SurveyCtxMenu(aladin, self); - - this.panels = { - stack, overlay, goto, grid, settings, survey - }; - - this.indices = []; - - this.aladin = aladin; } closeAll() { diff --git a/src/js/gui/widgets/ActionButton.js b/src/js/gui/widgets/ActionButton.js index fb293f04..fa384498 100644 --- a/src/js/gui/widgets/ActionButton.js +++ b/src/js/gui/widgets/ActionButton.js @@ -81,7 +81,7 @@ export class ActionButton extends DOMElement { if (Utils.hasTouchScreen()) { // Add a little padding - el.style.padding = "0.3em"; + el.style.padding = "0.2em"; } // add it to the dom diff --git a/src/js/gui/widgets/Box.js b/src/js/gui/widgets/Box.js index ed8cd403..7a993f37 100644 --- a/src/js/gui/widgets/Box.js +++ b/src/js/gui/widgets/Box.js @@ -18,7 +18,6 @@ // import { DOMElement } from "./Widget"; -import { Utils } from "../Utils"; import { ActionButton } from "./ActionButton"; import moveIconImg from '../../../../assets/icons/move.svg'; import { Layout } from "../Layout"; @@ -46,14 +45,19 @@ import { Form } from "./Form"; },] */ export class Box extends DOMElement { - constructor(options, target, position = "beforeend") { + constructor(aladin, options, position = "beforeend") { let el = document.createElement("div"); el.classList.add('aladin-box'); el.style.display = "initial"; super(el, options); + let target = aladin.aladinDiv; // add it to the dom this.attachTo(target, position); + + this.aladin = aladin; + + this._hide(); } _hide() { @@ -185,7 +189,7 @@ export class Box extends DOMElement { } if (this.options.position) { - this.setPosition(this.options.position) + this.setPosition({...this.options.position, aladinDiv: this.aladin.aladinDiv}) } } } @@ -198,7 +202,7 @@ export class SelectBox extends Box { * @param {String} position - The position of the tabs layout relative to the target. * For the list of possibilities, see https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML */ - constructor(options, target, position = "beforeend") { + constructor(aladin, options, position = "beforeend") { let labels = options.possibilities.map((opt) => opt.label); let value = (options && options.selected) || labels[0]; @@ -235,7 +239,7 @@ export class SelectBox extends Box { layout: [settingsSelector, selectedContent.content] }); - super(options, target, position); + super(aladin, options, position); self = this; } } diff --git a/src/js/gui/widgets/ContextMenu.js b/src/js/gui/widgets/ContextMenu.js index 1815f9fa..ad3e4066 100644 --- a/src/js/gui/widgets/ContextMenu.js +++ b/src/js/gui/widgets/ContextMenu.js @@ -96,7 +96,7 @@ export class ContextMenu extends DOMElement { } item.innerHTML = '' + posStr + ''; } catch (e) { - item.innerHTML = ''; + item.innerHTML = 'Out of projection'; } } else { if (opt.label instanceof DOMElement) { @@ -157,7 +157,10 @@ export class ContextMenu extends DOMElement { } if (opt.subMenu && opt.subMenu.length > 0) { - item.innerHTML += ''; + let spanEl = document.createElement('span') + spanEl.innerText = '▶'; + + item.appendChild(spanEl); item.style.display = 'flex'; item.style.alignItems = 'center'; item.style.justifyContent = 'space-between'; @@ -171,8 +174,27 @@ export class ContextMenu extends DOMElement { if (opt.selected && opt.selected === true) { item.classList.add('aladin-context-menu-item-selected'); } + + if (opt.subMenu) { + item.addEventListener('click', e => { + e.preventDefault(); + e.stopPropagation(); - if (opt.action) { + if (item.parentNode) { + let subMenus = item.parentNode.querySelectorAll(".aladin-context-sub-menu") + for (let subMenuChild of subMenus) { + subMenuChild.style.display = 'none'; + } + } + + item.querySelector(".aladin-context-sub-menu") + .style.display = 'block'; + + if (opt.action && (!opt.disabled || opt.disabled === false)) { + opt.action(e); + } + }); + } else if (opt.action) { item.addEventListener('click', o => { o.stopPropagation(); @@ -186,38 +208,7 @@ export class ContextMenu extends DOMElement { } } }); - } else if (opt.subMenu) { - item.addEventListener('click', e => { - console.log("click on item") - e.preventDefault(); - e.stopPropagation(); - - if (item.parentNode) { - let subMenus = item.parentNode.querySelectorAll(".aladin-context-sub-menu") - for (let subMenuChild of subMenus) { - subMenuChild.style.display = 'none'; - } - } - - item.querySelector(".aladin-context-sub-menu") - .style.display = 'block'; - }); } - - if (opt.hover) { - item.addEventListener('mouseover', e => { - e.stopPropagation(); - opt.hover(e, item); - }) - } - if (opt.unhover) { - item.addEventListener('mouseout', e => { - e.stopPropagation(); - opt.unhover(e, item); - }) - } - - target.appendChild(item); if (opt.subMenu && opt.subMenu.length) { const subMenu = document.createElement('ul'); @@ -234,36 +225,70 @@ export class ContextMenu extends DOMElement { item.appendChild(subMenu); opt.subMenu.forEach(subOpt => this._attachOption(subMenu, subOpt, e, cssStyle)); } + + + if (opt.hover) { + item.addEventListener('mouseover', e => { + e.stopPropagation(); + e.preventDefault(); + + opt.hover(e, item); + }) + } + + if (opt.unhover) { + item.addEventListener('mouseout', e => { + e.stopPropagation(); + e.preventDefault(); + + opt.unhover(e, item); + }) + } + + target.appendChild(item); } _subMenuDisplay(parent) { + const {offsetWidth, offsetHeight} = this.aladin.aladinDiv; + const aladinRect = this.aladin.aladinDiv.getBoundingClientRect(); + + let leftDir = 0; + let topDir = 0; + for (let item of parent.children) { - // Display the submenu to evaluate its size item.style.display = "block"; - if (item.className === 'aladin-context-sub-menu') { - let r = item.getBoundingClientRect(); - const {offsetWidth, offsetHeight} = this.aladin.aladinDiv; + let r = item.getBoundingClientRect(); - if (r.x + r.width >= offsetWidth) { - this.el.classList.add('left'); - } - - if (r.y + r.height >= offsetHeight) { - this.el.classList.add('top'); - } + if (r.x - aladinRect.left <= offsetWidth / 2.0) { + leftDir -= 1; + } else { + leftDir += 1; } - this._subMenuDisplay(item) + if (r.y - aladinRect.top <= offsetHeight / 2.0) { + topDir -= 1; + } else { + topDir += 1; + } - // Hide the submenu item.style.display = ""; } + + if (leftDir > 0) { + this.el.classList.add('left'); + } else { + this.el.classList.add('right'); + } + + if (topDir > 0) { + this.el.classList.add('top'); + } else { + this.el.classList.add('bottom'); + } } show(options) { - //this.remove(); - this.el.innerHTML = ''; this.el.style = this.cssStyleDefault @@ -286,7 +311,7 @@ export class ContextMenu extends DOMElement { top: options.e.clientY - this.aladin.aladinDiv.offsetTop }); - this.setPosition(position) + this.setPosition({...position, aladinDiv: this.aladin.aladinDiv}) this.el.classList.remove('left') this.el.classList.remove('top') diff --git a/src/js/gui/widgets/Input.js b/src/js/gui/widgets/Input.js index aeda8d16..73f6b616 100644 --- a/src/js/gui/widgets/Input.js +++ b/src/js/gui/widgets/Input.js @@ -19,6 +19,7 @@ import { DOMElement } from "./Widget"; import { Tooltip } from "./Tooltip"; +import { Utils } from "../../Utils"; /****************************************************************************** * Aladin Lite project * @@ -172,6 +173,12 @@ export class Input extends DOMElement { Tooltip.add(this.options.tooltip, this) } + // 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/Toolbar.js b/src/js/gui/widgets/Toolbar.js index 58e1ccf9..e4c19681 100644 --- a/src/js/gui/widgets/Toolbar.js +++ b/src/js/gui/widgets/Toolbar.js @@ -59,30 +59,68 @@ export class Toolbar extends Layout { * For the list of possibilities, see https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML */ constructor(options) { - options.direction = options.direction || 'horizontal'; + options.orientation = options.orientation || 'horizontal'; + + if (options.direction === undefined) { + options.direction = options.orientation === 'horizontal' ? 'bottom' : 'left'; + } + options.position = options.position || {anchor: 'left top'}; options.layout = options.layout || []; super(options) - let direction = options.direction; - if (direction === 'vertical') { - this.addClass('aladin-vertical-list') - } else { - this.addClass('aladin-horizontal-list') - } + this.addClass(options.direction); this.tools = {}; } - add(tools) { - if (!Array.isArray(tools)) { - tools = [tools]; + update(options) { + if (options.direction) { + this.removeClass('left'); + this.removeClass('right'); + this.removeClass('top'); + this.removeClass('bottom'); + + this.addClass(options.direction) + + // search for a tooltip + this.el.querySelectorAll(".aladin-tooltip-container") + .forEach((t) => { + t.classList.remove('left'); + t.classList.remove('right'); + t.classList.remove('top'); + t.classList.remove('bottom'); + + t.classList.add(options.direction === 'left' ? 'right' : 'left'); + }) } - tools.forEach(tool => { - this.appendAtLast(tool) - }); + super.update(options); + } + + add(tool, name, position = 'after') { + if (Array.isArray(tool)) { + let tools = tool; + tools.forEach(t => { + this.appendAtLast(t) + }); + } else { + if (position === 'begin') { + this.appendAtIndex(tool, name, 0) + } else { + this.appendAtLast(tool, name) + } + } + } + + remove(name) { + let tool = this.tools[name]; + + this.removeItem(tool) + delete this.tools[name]; + + return tool; } appendAtLast(tool, name) { diff --git a/src/js/gui/widgets/Widget.js b/src/js/gui/widgets/Widget.js index 7b9cb320..615f22a2 100644 --- a/src/js/gui/widgets/Widget.js +++ b/src/js/gui/widgets/Widget.js @@ -108,6 +108,19 @@ export class DOMElement { setPosition(options) { let el = this.element(); + el.classList.remove('aladin-anchor-left'); + el.classList.remove('aladin-anchor-right'); + el.classList.remove('aladin-anchor-center'); + el.classList.remove('aladin-anchor-top'); + el.classList.remove('aladin-anchor-bottom'); + el.classList.remove('aladin-anchor-middle'); + + delete el.style.removeProperty("left"); + delete el.style.removeProperty("right"); + delete el.style.removeProperty("top"); + delete el.style.removeProperty("bottom"); + delete el.style.removeProperty("transform"); + if (options && options.anchor) { el.style.position = 'absolute'; @@ -132,11 +145,11 @@ export class DOMElement { } let left = 0, top = 0, bottom, right; - let x = 0, y = 0; + let x, y; // handle the anchor/dir case with higher priority const {offsetWidth, offsetHeight} = el; - const aladinDiv = document.querySelector('.aladin-container'); + const aladinDiv = options.aladinDiv || document.querySelector('.aladin-container'); const innerWidth = aladinDiv.offsetWidth; const innerHeight = aladinDiv.offsetHeight; @@ -145,16 +158,16 @@ export class DOMElement { if (options && (options.left || options.top || options.right || options.bottom)) { el.style.position = 'absolute'; - if (options.top) { + if (options.top !== undefined) { top = options.top; } - if (options.left) { + if (options.left !== undefined) { left = options.left; } - if (options.bottom) { + if (options.bottom !== undefined) { bottom = options.bottom; } - if (options.right) { + if (options.right !== undefined) { right = options.right; } } else if (options && options.nextTo && options.direction) { @@ -192,7 +205,7 @@ export class DOMElement { left = 0; top = 0; break; - } + } } // Translate if the div in @@ -212,20 +225,20 @@ export class DOMElement { y = Math.abs(top) + 'px'; } - if (top !== undefined) { - el.style.top = top + 'px'; - } - if (left !== undefined) { - el.style.left = left + 'px'; - } if (bottom !== undefined) { el.style.bottom = bottom + 'px'; - } - if (right !== undefined) { - el.style.right = right + 'px'; + } else { + el.style.top = top + 'px'; } - el.style.transform = `translate(${x}, ${y})`; + if (right !== undefined) { + el.style.right = right + 'px'; + } else { + el.style.left = left + 'px'; + } + + if (x && y) + el.style.transform = `translate(${x}, ${y})`; } _show() {