diff --git a/Cargo.lock b/Cargo.lock index b0fc950..a9a07ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -201,55 +201,6 @@ dependencies = [ "libc", ] -[[package]] -name = "anstream" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" - -[[package]] -name = "anstyle-parse" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "anstyle-wincon" -version = "3.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" -dependencies = [ - "anstyle", - "windows-sys 0.52.0", -] - [[package]] name = "anyhow" version = "1.0.86" @@ -830,7 +781,7 @@ dependencies = [ "proj-sys", "quadtree_rs", "quick_cache", - "radarg_data", + "radarg_core", "radarg_plugin_interface", "rayon", "regex", @@ -851,7 +802,6 @@ dependencies = [ "thiserror", "tokio", "tokio-condvar", - "toml", "topojson", "tracing", "tracing-subscriber", @@ -935,12 +885,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" -[[package]] -name = "colorchoice" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" - [[package]] name = "combine" version = "4.6.7" @@ -1331,29 +1275,6 @@ dependencies = [ "syn 2.0.75", ] -[[package]] -name = "env_filter" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2c92ceda6ceec50f43169f9ee8424fe2db276791afde7b2cd8bc084cb376ab" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "env_logger" -version = "0.11.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13fa619b91fb2381732789fc5de83b45675e882f66623b7d8cb4f643017018d" -dependencies = [ - "anstream", - "anstyle", - "env_filter", - "humantime", - "log", -] - [[package]] name = "epoxy" version = "0.1.0" @@ -1918,7 +1839,6 @@ dependencies = [ "chrono", "copypasta", "dirs", - "env_logger", "femtovg", "flate2", "freetype-rs", @@ -1939,9 +1859,10 @@ dependencies = [ "nom-derive", "once_cell", "pathfinder_geometry", - "radarg_data", + "radarg_core", "raw-window-handle", "regex", + "relm4", "rust-embed", "serde", "serde_json", @@ -2567,12 +2488,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "humantime" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" - [[package]] name = "hyper" version = "0.14.30" @@ -2796,12 +2711,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" -[[package]] -name = "is_terminal_polyfill" -version = "1.70.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" - [[package]] name = "itertools" version = "0.11.0" @@ -4289,13 +4198,21 @@ dependencies = [ ] [[package]] -name = "radarg_data" +name = "radarg_core" version = "0.1.0" dependencies = [ "chrono", + "dirs", "ndarray 0.16.1", + "num-traits", + "proj", + "proj-sys", "radarg_plugin_interface", + "relm4", + "rust-embed", + "serde", "thiserror", + "toml", ] [[package]] @@ -4821,18 +4738,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff085d2cb684faa248efb494c39b68e522822ac0de72ccf08109abde717cfb2" +checksum = "99fce0ffe7310761ca6bf9faf5115afbc19688edd00171d81b1bb1b116c63e09" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.208" +version = "1.0.209" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24008e81ff7613ed8e5ba0cfaf24e2c2f1e5b8a0495711e44fcd4882fca62bcf" +checksum = "a5831b979fd7b5439637af1752d535ff49f4860c0f341d1baeb6faf0f4242170" dependencies = [ "proc-macro2 1.0.86", "quote 1.0.37", @@ -5781,12 +5698,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - [[package]] name = "v_frame" version = "0.3.8" diff --git a/Cargo.toml b/Cargo.toml index 9d0f784..d8de7e8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,5 +6,5 @@ members = [ "geo-macros", "radar-g", "gi", - "radarg_data", + "radarg_core", ] diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..971cab0 --- /dev/null +++ b/config.toml @@ -0,0 +1,217 @@ +[[cmap]] +type = "DBZ" +levels = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75] +colors = [ + "#aaaaaa", + "#0022ff", + "#01a0f6", + "#00ecec", + "#00d800", + "#019000", + "#ffff00", + "#e7c000", + "#ff9000", + "#ff0000", + "#d60000", + "#c00000", + "#ff00f0", + "#9600b4", + "#ad90f0", +] + +[[cmap]] +type = "VEL" +levels = [ + -90, + -45, + -35, + -27, + -20, + -15, + -10, + -5, + -1, + 0, + 1, + 5, + 10, + 15, + 20, + 27, + 1000, +] +colors = [ + "#9fffff", + "#00e0ff", + "#0080ff", + "#320096", + "#00fb90", + "#00bb90", + "#008f00", + "#cdc09f", + "#000000", + "#f88700", + "#ffcf00", + "#ffff00", + "#ae0000", + "#d07000", + "#dd0000", + "#ff0000", +] + +[[cmap]] +type = "SW" +colors = [ + "#E0E0E0", + "#7CE0E0", + "#00E0E0", + "#00B0B0", + "#00FEFE", + "#00C400", + "#008000", + "#FEFE00", + "#FED200", + "#FE7C00", + "#FEB0B0", + "#FE5858", + "#FE0000", + "#FEFEFE", +] +levels = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] + +[[cmap]] +type = "CC" +colors = [ + "#003CFF", + "#00EFEF", + "#00BABF", + "#00837D", + "#008938", + "#00B729", + "#00DA0D", + "#00FF00", + "#FFFF3B", + "#FFF000", + "#FFC600", + "#FFA500", + "#FF7200", + "#FF1F00", + "#C10000", + "#D400AA", +] +levels = [ + 0, + 0.1, + 0.3, + 0.5, + 0.6, + 0.7, + 0.8, + 0.85, + 0.9, + 0.92, + 0.94, + 0.95, + 0.96, + 0.97, + 0.98, + 0.99, +] + +[[cmap]] +type = "KDP" +colors = [ + "#00FFFF", + "#00EFEF", + "#00A8AC", + "#B4B4B4", + "#B4B4B4", + "#00C027", + "#00E80A", + "#24FF24", + "#FFFF1E", + "#FFE600", + "#FFBC00", + "#FF9800", + "#FF5E00", + "#F20F00", + "#BB003A", + "#DD009C", + "#FF00FF", +] +levels = [ + -0.8, + -0.4, + -0.2, + -0.1, + 0.1, + 0.15, + 0.22, + 0.33, + 0.5, + 0.75, + 1.1, + 1.7, + 2.4, + 3.1, + 7, + 20, +] + +[[cmap]] +type = "ZDR" +colors = [ + "#464646", + "#505050", + "#5A5A5A", + "#646464", + "#6E6E6E", + "#787878", + "#828282", + "#8C8C8C", + "#969696", + "#AFAFAF", + "#C8C8C8", + "#DCF0DC", + "#00C027", + "#00E80A", + "#24FF24", + "#FFFF1E", + "#FFF20F", + "#FFE600", + "#FFBC00", + "#FF9800", + "#FF5E00", + "#FFFF00", + "#F20F00", + "#BB003A", + "#DD009C", + "#FF00FF", +] +levels = [ + -5, + -4.5, + -4, + -3.5, + -3, + -2.5, + -2, + -1.5, + -1, + -0.5, + 0, + 0.5, + 1, + 1.5, + 2, + 2.5, + 3, + 3.5, + 4, + 4.5, + 5, + 5.5, + 6, + 6.5, + 7, +] diff --git a/gi/Cargo.toml b/gi/Cargo.toml index f245b10..db1a1cc 100644 --- a/gi/Cargo.toml +++ b/gi/Cargo.toml @@ -12,7 +12,6 @@ cgmath = "0.18.0" chrono = "0.4.38" copypasta = "0.10.1" dirs = "5.0.1" -env_logger = "0.11.3" flate2 = "1.0.30" freetype-rs = { version = "0.37.0", features = ["bundled"] } geo = "0.28.0" @@ -43,7 +42,7 @@ toml = "0.8.19" femtovg = "0.9.2" rust-embed = "8.5.0" tempfile = "3.12.0" -radarg_data = { path = "../radarg_data" } +relm4 = { version = "0.9.0", features = ["libadwaita"] } [features] default = ["sdf_font"] @@ -57,3 +56,6 @@ femtovg = [] [lib] name = "gi" + +[dependencies.radarg_core] +path = "../radarg_core" diff --git a/gi/src/camera.rs b/gi/src/camera.rs index b611238..ecaf712 100644 --- a/gi/src/camera.rs +++ b/gi/src/camera.rs @@ -4,7 +4,7 @@ use nalgebra_glm::{look_at, Mat4x4, Vec3}; use std::num::NonZeroU32; #[derive(Clone)] -pub(crate) struct Camera { +pub struct Camera { pos: Vec3, upward: Vec3, center: Vec3, diff --git a/gi/src/graphics/colormap/linear.rs b/gi/src/graphics/colormap/linear.rs index a1216af..e3af7a5 100644 --- a/gi/src/graphics/colormap/linear.rs +++ b/gi/src/graphics/colormap/linear.rs @@ -28,13 +28,17 @@ impl LinearColormap { } pub fn set_unvalid_value(&mut self, value: f32) { - self.unvalid = value; - self.color_changed = true; + if value != self.unvalid { + self.unvalid = value; + self.color_changed = true; + } } pub fn set_colors(&mut self, colors: Vec<[u8; 4]>) { - self.colors = colors; - self.color_changed = true; + if colors != self.colors { + self.colors = colors; + self.color_changed = true; + } } pub fn set_range(&mut self, min: f32, max: f32) { @@ -104,6 +108,9 @@ impl ColorMap for LinearColormap { gl.active_texture(glow::TEXTURE0); gl.bind_texture(glow::TEXTURE_1D, self.texture); let location = program.get_uniform_location(gl, "colormap"); + + let error = gl.get_error(); + gl.uniform_1_i32(location.as_ref(), 0); } diff --git a/gi/src/graphics/ppi.rs b/gi/src/graphics/ppi.rs index 9a89375..fc3f3fc 100644 --- a/gi/src/graphics/ppi.rs +++ b/gi/src/graphics/ppi.rs @@ -7,7 +7,7 @@ use crate::components::{Program, Shader}; use crate::errors::*; use crate::graphics::colormap::linear::LinearColormap; use glow::{HasContext, NativeBuffer, NativeVertexArray}; -use radarg_data::{CoordType, ProbeDataType, RadarGridData}; +use radarg_core::radarg_data::{CoordType, ProbeDataType, RadarGridData}; pub struct PPI { program: Program, @@ -201,10 +201,12 @@ impl AttaWithBuffer for PPI { let mut vertices = Vec::with_capacity(azimuth_len * r_len); let ele = *elevation.unwrap().get(layer).unwrap() as f32; + let last_range = *range.last().unwrap() as f32; + for azi_idx in 0..azimuth_len { for r_idx in 0..r_len { let azi = *azimuth.get(azi_idx).unwrap() as f32; - let r = *range.get(r_idx).unwrap() as f32 / range[1] as f32; + let r = *range.get(r_idx).unwrap() as f32 / last_range; let data = &data.data; let dt = data.get([layer, azi_idx, r_idx]).unwrap(); vertices.extend([r, azi, ele, *dt]); diff --git a/gi/src/graphics/transforms/plane.rs b/gi/src/graphics/transforms/plane.rs index b096cad..9a2da0c 100644 --- a/gi/src/graphics/transforms/plane.rs +++ b/gi/src/graphics/transforms/plane.rs @@ -59,8 +59,8 @@ impl AttachWithIO for PlaneTrans { // let shift_key = state.keyboard_state[imgui::Key::LeftShift as usize]; // let ctrl_key = state.keyboard_state[imgui::Key::LeftCtrl as usize]; - let shift_key = true; - let ctrl_key = true; + let shift_key = false; + let ctrl_key = false; match &state.mouse_state { MouseState::Drag { from, delta } => { diff --git a/gi/src/lib.rs b/gi/src/lib.rs index 070a28a..79fe334 100644 --- a/gi/src/lib.rs +++ b/gi/src/lib.rs @@ -6,7 +6,6 @@ mod errors; mod font_manager; pub mod graphics; pub mod pg; -mod setting; mod shaders; pub mod ui; mod utils; diff --git a/gi/src/pg/app.rs b/gi/src/pg/app.rs index bd38766..f08d7f7 100644 --- a/gi/src/pg/app.rs +++ b/gi/src/pg/app.rs @@ -1,5 +1,5 @@ use log::*; -use radarg_data::Data; +use radarg_core::radarg_data::Data; use std::{cell::RefCell, path::PathBuf, rc::Rc}; use crate::{ @@ -61,8 +61,12 @@ impl App { &mut self.context.programs } - pub fn load_data(&mut self, data: &Vec) -> Result { - self.program().load_data(data) + pub fn load_data( + &mut self, + data: &Vec, + setting: &radarg_core::config::Setting, + ) -> Result { + self.program().load_data(data, setting) } } diff --git a/gi/src/pg/mod.rs b/gi/src/pg/mod.rs index 92f4639..867594e 100644 --- a/gi/src/pg/mod.rs +++ b/gi/src/pg/mod.rs @@ -3,7 +3,14 @@ use femtovg::renderer::OpenGl; use femtovg::Canvas; use glow::HasContext; use layout_type::ViewPort; -use radarg_data::Data; +use modules::PPIModuleConfigComponent; +use radarg_core::radarg_data::Data; +use relm4::{ + gtk, + gtk::prelude::{Cast, IsA}, + gtk::Widget, + Component, ComponentBuilder, Controller, Sender, +}; pub mod layout_type; mod modules; @@ -20,10 +27,19 @@ use crate::utils::resources::GL; use crate::{errors::*, graphics::Graphics}; pub use app::{App, Context}; pub use modules::{Module, ModuleCursor, PPIModule, PPIPackage}; +use std::cell::RefCell; +use std::rc::Rc; use std::sync::atomic::AtomicUsize; static MODULE_PACKAGE_ID: AtomicUsize = AtomicUsize::new(0); +#[derive(Debug)] +pub enum SideBarInputMsg { + Package(Rc>), + Refresh, + None, +} + pub struct Programs { gl: GL, _ppi: PPI, @@ -61,10 +77,16 @@ impl Programs { PPIModule::new(&self.gl, &mut self._ppi, &mut self._text, &mut self._line) } - pub fn load_data(&mut self, data: &Vec) -> Result { + pub fn load_data( + &mut self, + data: &Vec, + setting: &radarg_core::config::Setting, + ) -> Result { let data = &data[0]; match data { - Data::RadarGridData(ref grid_data) => self.ppi().load_data(grid_data).map(|v| v.into()), + Data::RadarGridData(ref grid_data) => { + self.ppi().load_data(grid_data, setting).map(|v| v.into()) + } _ => Err(Error::InvalidDataType), } } @@ -86,7 +108,15 @@ impl Programs { } macro_rules! impl_module_package { - ($({$t:ty => $b: tt}),+) => { + ($({$t:ty => $b: tt | $c: ty}),+) => { + + #[derive(Debug)] + pub enum _ModulePackage { + $( + $b($t), + )+ + } + $( impl From<$t> for _ModulePackage { @@ -95,43 +125,86 @@ macro_rules! impl_module_package { } } )+ + + pub enum ComponentBuilders { + $( + $b(ComponentBuilder<$c>, Rc::Config>>, Box::ComponentOutput) -> SideBarInputMsg>), + )+ + } + + pub enum Components { + $( + $b(Controller<$c>), + )+ + } + + impl Components { + pub fn widget(&self) -> gtk::Widget{ + + use relm4::ComponentController; + match self { + $( + Components::$b(c) => c.widget().clone().upcast(), + )+ + } + } + } + + #[derive(Debug)] + pub struct ModulePackage { + id: usize, + pub need_update: bool, + modules: _ModulePackage, + } + + impl ModulePackage { + + pub fn component_builder(&self) -> ComponentBuilders { + match &self.modules { + $( + _ModulePackage::$b(t) => ComponentBuilders::$b(<$c as Component>::builder(), t.component_config(), t.component_sender()), + )+ + } + } + + } + + impl ComponentBuilders { + pub fn build>(self, package: &ModulePackage, root: &ROOT, sender: &Sender) -> Components { + match self { + $( + ComponentBuilders::$b(b, init, f) => Components::$b(b.launch(init).forward(sender, move |c| {f(c)})), + )+ + } + } + } + + + impl From for ModulePackage + where + T: ModuleCursor + Into<_ModulePackage>, + { + fn from(t: T) -> Self { + Self { + id: MODULE_PACKAGE_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst), + modules: t.into(), + need_update: true, + } + } + } + + impl PartialEq for ModulePackage { + fn eq(&self, other: &Self) -> bool { + self.id == other.id + } + } + }; } -#[derive(Debug)] -pub struct ModulePackage { - id: usize, - pub need_update: bool, - modules: _ModulePackage, -} - -#[derive(Debug)] -pub enum _ModulePackage { - PPI(PPIPackage), -} - -impl_module_package!({ - PPIPackage => PPI -}); - -impl From for ModulePackage -where - T: ModuleCursor + Into<_ModulePackage>, -{ - fn from(t: T) -> Self { - Self { - id: MODULE_PACKAGE_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst), - modules: t.into(), - need_update: true, - } - } -} - -impl PartialEq for ModulePackage { - fn eq(&self, other: &Self) -> bool { - self.id == other.id - } -} +impl_module_package!( + {PPIPackage => PPI | PPIModuleConfigComponent} +); impl ModulePackage { pub fn dirty(&mut self) { diff --git a/gi/src/pg/modules/mod.rs b/gi/src/pg/modules/mod.rs index ae852e2..82c653b 100644 --- a/gi/src/pg/modules/mod.rs +++ b/gi/src/pg/modules/mod.rs @@ -1,5 +1,3 @@ -use std::rc::Rc; - use crate::{ graphics::AttachWithIO, resources::{RcGlRcBuffer, RcGlRcVertexArray}, @@ -12,11 +10,14 @@ use crate::{ }; use femtovg::{renderer::OpenGl, Canvas}; use glow::{HasContext, NativeBuffer, NativeVertexArray}; +use radarg_core::config::Setting; +use std::{cell::RefCell, path::Component, rc::Rc}; mod ppi; use crate::errors::*; -pub use ppi::{PPIModule, PPIPackage}; +pub use ppi::{PPIModule, PPIModuleConfigComponent, PPIModuleConfigComponentWidgets, PPIPackage}; +use relm4::Component as RComponent; -use super::layout_type::ViewPort; +use super::{layout_type::ViewPort, SideBarInputMsg}; #[derive(Clone, Debug)] struct Attach { @@ -101,15 +102,22 @@ pub trait Module: Sized { viewport: &ViewPort, ) -> Result<()>; - fn load_data<'dt>(&self, data: &Rc) -> Result; + fn load_data<'dt>(&self, data: &Rc, setting: &Setting) -> Result; } pub trait ModuleCursor { type Module<'rf, 'gl: 'rf>: Module; type Data; type Config; + type Component: RComponent; + + type ComponentOutput; fn set_config(&mut self, f: F) where F: FnOnce(&mut Self::Config); + + fn component_config(&self) -> Rc>; + + fn component_sender(&self) -> Box SideBarInputMsg>; } diff --git a/gi/src/pg/modules/ppi.rs b/gi/src/pg/modules/ppi.rs index 77d6f8a..ab2679d 100644 --- a/gi/src/pg/modules/ppi.rs +++ b/gi/src/pg/modules/ppi.rs @@ -6,12 +6,22 @@ use crate::{ transforms::plane::PlaneTrans, AttaWithBuffer, Graphics, }, + pg::SideBarInputMsg, GL, }; +use radarg_core::config::Setting; +use relm4::{ + adw::{self, prelude::*}, + gtk::{self, prelude::*}, + ComponentParts, SimpleComponent, +}; use core::f32; use glow::HasContext; -use std::rc::Rc; +use std::{ + cell::{RefCell, RefMut}, + rc::Rc, +}; use tracker::track; use crate::font_manager::{FontSize, FontStyle}; @@ -20,7 +30,7 @@ use crate::pg::layout_type::ViewPort; use crate::ui::operation::{self, Operation}; use crate::{errors::*, font_manager::FontManager, ui::typ, utils::resources::ManagedResource}; -use radarg_data::RadarGridData; +use radarg_core::radarg_data::RadarGridData; use super::{Attach, Module, ModuleCursor}; pub struct PPIModule<'b, 'gl: 'b> { @@ -154,14 +164,16 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { operation: &Operation, viewport: &ViewPort, ) -> Result<()> { + // PPI Program + let data = &cursor.data; + let mut config = &mut cursor.ppi_config.borrow_mut(); + // Mount PPI Program self.ppi_program.mount(&self.gl)?; // Deal with the operation operation.attach_with_program(&self.gl, self.ppi_program.program()); - // PPI Program + let ppi_attach = &mut cursor.ppi_attach; - let data = &cursor.data; - let config = &mut cursor.ppi_config; // Update the config self.ppi_program @@ -172,13 +184,6 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { self.bind_ppi_pg(ppi_attach, data, config); } - if config.changed_range_line_num() - || config.changed_ath_line_num() - || config.changed_vertical_axis() - { - self.bind_line_pg(&mut cursor.line_attach, data, config)?; - } - // PPI Draw ppi_attach.bind_self(); self.ppi_program.draw(&self.gl, ppi_attach.len())?; @@ -187,6 +192,13 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { // Unmount PPI Program self.ppi_program.unmount(&self.gl)?; + if config.changed_range_line_num() + || config.changed_ath_line_num() + || config.changed_vertical_axis() + { + self.bind_line_pg(&mut cursor.line_attach, data, config)?; + } + // Mount Line Program self.line_program.mount(&self.gl)?; @@ -226,7 +238,7 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { Ok(()) } - fn load_data<'dt>(&self, data: &Rc) -> Result { + fn load_data<'dt>(&self, data: &Rc, setting: &Setting) -> Result { // Init the memory let (vao, vbo, ebo) = self.ppi_program.init(&self.gl); let mut ppi_attach = Attach::new(self.gl.clone(), vao, vbo, ebo, None); @@ -235,15 +247,13 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { let (r, a, t, max_layer, unvalid) = self.ppi_program.data_info(&data)?; // Find the color map - // let cmap = SETTING.find(&t); - - // let cmap = None; + let cmap = setting.find(&t); // Check if the color map is valid - // if cmap.is_none() { - // return Err(Error::InvalidDataType); - // } - // let cmap = cmap.unwrap(); + if cmap.is_none() { + return Err(Error::InvalidDataType); + } + let cmap = cmap.unwrap(); // Init the memory for the line program let (vao, vbo, ebo) = self.line_program.init(&self.gl); @@ -258,8 +268,8 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { config.adpi = a; config.max_layer = max_layer; config.unvalid_value = unvalid; - // config.colors = cmap.color()?; - // config.color_range = cmap.value_range(); + config.colors = cmap.color().unwrap(); + config.color_range = cmap.value_range(); // Bind the data self.bind_ppi_pg(&mut ppi_attach, &data, &config); @@ -280,7 +290,7 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> { #[derive(Debug)] pub struct PPIPackage { draw_helper: bool, - ppi_config: PPIModuleConfig, + ppi_config: Rc>, ppi_attach: Attach, line_attach: Attach, tick_attach: Attach, @@ -297,7 +307,7 @@ impl PPIPackage { ) -> Self { Self { draw_helper: true, - ppi_config, + ppi_config: Rc::new(RefCell::new(ppi_config)), ppi_attach, line_attach, tick_attach, @@ -307,7 +317,7 @@ impl PPIPackage { } #[track] -#[derive(PartialEq, Debug)] +#[derive(PartialEq, Debug, Clone)] pub struct PPIModuleConfig { pub ticks: bool, pub line_color: [f32; 4], @@ -388,15 +398,92 @@ impl PPIModuleConfig { } } +pub struct PPIModuleConfigComponent { + config: Rc>, +} + +#[derive(Debug)] +pub enum OutputMsg { + Refresh, +} + +#[relm4::component(pub)] +impl SimpleComponent for PPIModuleConfigComponent { + type Widgets = PPIModuleConfigComponentWidgets; + type Init = Rc>; + type Input = (); + type Output = OutputMsg; + + view! { + adw::PreferencesGroup { + set_title:"PPI Config", + set_hexpand:true, + set_vexpand:true, + adw::SwitchRow { + set_title:"Ticks", + set_active: init_config.ticks, + connect_active_notify[sender, config_ref] => move |this| { + let active = this.is_active(); + config_ref.borrow_mut().set_ticks(active); + } + }, + adw::SpinRow { + set_title: "Layer", + set_value: init_config.layer as f64, + set_range: (0.0, init_config.max_layer as f64), + set_digits: 0, + set_numeric: true, + set_climb_rate: 1.0, + connect_value_notify[sender, config_ref] => move |this| { + let layer = this.value() as usize; + config_ref.borrow_mut().set_layer(layer); + } + } + } + } + + fn init( + init: Self::Init, + root: Self::Root, + sender: relm4::ComponentSender, + ) -> relm4::ComponentParts { + let model = PPIModuleConfigComponent { + config: init.clone(), + }; + let init_config = init.borrow().clone(); + let config_ref = model.config.clone(); + + let widgets = view_output!(); + + ComponentParts { model, widgets } + } + + fn update(&mut self, message: Self::Input, sender: relm4::ComponentSender) {} +} + impl ModuleCursor for PPIPackage { type Module<'rf, 'gl: 'rf> = PPIModule<'rf, 'gl>; type Config = PPIModuleConfig; type Data = RadarGridData; + type Component = PPIModuleConfigComponent; + + type ComponentOutput = OutputMsg; fn set_config(&mut self, f: F) where F: FnOnce(&mut Self::Config), { - f(&mut self.ppi_config); + let mut config = self.ppi_config.borrow_mut(); + f(&mut config); + } + + fn component_config(&self) -> Rc> { + self.ppi_config.clone() + } + + fn component_sender(&self) -> Box crate::pg::SideBarInputMsg> { + Box::new(|c| match c { + OutputMsg::Refresh => SideBarInputMsg::Refresh, + }) } } diff --git a/gi/src/ui/io.rs b/gi/src/ui/io.rs index bccba1b..148aeb6 100644 --- a/gi/src/ui/io.rs +++ b/gi/src/ui/io.rs @@ -1,3 +1,4 @@ +#[derive(Debug, Default)] pub struct MouseIO { pub position: [f32; 2], // 鼠标当前位置 pub drag_delta: Option<[f32; 2]>, // 拖动开始时的鼠标位置 @@ -5,12 +6,21 @@ pub struct MouseIO { pub left_button_pressed: bool, // 左键是否被按下 pub right_button_pressed: bool, // 右键是否被按下 pub wheel_delta: f32, // 鼠标滚轮变化值 + pub drag_sum: [f32; 2], // 拖动累计值 } +#[derive(Debug)] pub struct KeyboardIO { pub keys: [bool; 652], // 键盘按键状态 } +impl Default for KeyboardIO { + fn default() -> Self { + Self { keys: [false; 652] } + } +} + +#[derive(Debug, Default)] pub struct IO { pub mouse: MouseIO, pub keyboard: KeyboardIO, diff --git a/radar-g/Cargo.toml b/radar-g/Cargo.toml index 4b6020a..47448a5 100644 --- a/radar-g/Cargo.toml +++ b/radar-g/Cargo.toml @@ -53,7 +53,6 @@ abi_stable = "0.11.3" serde = "1.0.196" serde_json = "1.0.112" flate2 = "1.0.28" -toml = "0.8.8" dirs = "5.0.1" regex = "1.10.3" smallvec = "1.13.1" @@ -86,8 +85,8 @@ path = "../radarg_plugin_interface" [dependencies.gi] path = "../gi" -[dependencies.radarg_data] -path = "../radarg_data" +[dependencies.radarg_core] +path = "../radarg_core" #[dependencies.etws_loader] #path = "etws_loader" diff --git a/radar-g/config.toml b/radar-g/config.toml deleted file mode 100644 index 5c4fe15..0000000 --- a/radar-g/config.toml +++ /dev/null @@ -1,2 +0,0 @@ -[plugins] -etws_loader = { version = "0.1.0" } diff --git a/radar-g/src/components/app.rs b/radar-g/src/components/app.rs index 073c2c8..05e5b32 100644 --- a/radar-g/src/components/app.rs +++ b/radar-g/src/components/app.rs @@ -9,11 +9,8 @@ use super::{ use crate::components::sidebar::{SideBarInputMsg, SideBarModel}; use crate::datapool::{DataPool, Value}; use crate::predefined::color_mapper::{BoundaryNorm, ColorMapper, ColorMapperComb, Discrete}; -use crate::predefined::widgets::ColorBar; use crate::widgets::{DynamicCol, ElementType}; -use crate::{ - errors::RenderError, plugin_system::init_plugin, widgets::render::Layer, PLUGIN_MANAGER, -}; +use crate::{plugin_system::init_plugin, widgets::render::Layer, PLUGIN_MANAGER}; use abi_stable::std_types::RStr; use adw::prelude::*; use chrono::{prelude::*, Duration}; @@ -24,7 +21,7 @@ use gtk::glib::clone; use gtk::prelude::*; use ndarray::{ArrayView1, ArrayViewD}; use once_cell::sync::Lazy; -use radarg_data::Data; +use radarg_core::Data; use relm4::actions::{AccelsPlus, RelmAction, RelmActionGroup}; use relm4::*; use relm4::{gtk, Component, ComponentParts, ComponentSender, RelmWidgetExt, SimpleComponent}; @@ -70,6 +67,7 @@ pub enum FileIOType { #[derive(Debug)] pub enum AppMsg { + Refresh, FileIO { typ: FileIOType }, CloseRequest, Close, @@ -82,8 +80,8 @@ pub struct AppModel { // Components #[do_not_track] open_dialog: Controller, - #[do_not_track] - control: Controller, + // #[do_not_track] + // control: Controller, #[do_not_track] render: Controller, #[do_not_track] @@ -160,7 +158,7 @@ impl Component for AppModel { set_hexpand: true, }, }, - model.control.widget(), + // model.control.widget(), #[name="monitor_toast"] adw::ToastOverlay{ set_hexpand: true, @@ -214,20 +212,23 @@ impl Component for AppModel { sender: ComponentSender, ) -> ComponentParts { let layers = Rc::new(RefCell::new(vec![])); - let control = ControlPanelModel::builder().launch(layers.clone()).forward( - sender.input_sender(), - |msg| match msg { - ControlPanelOutputMsg::OpenFile((key, time)) => AppMsg::Close, - }, - ); + // let control = ControlPanelModel::builder().launch(layers.clone()).forward( + // sender.input_sender(), + // |msg| match msg { + // ControlPanelOutputMsg::OpenFile((key, time)) => AppMsg::Close, + // }, + // ); let data_pool = DataPool::new(10); let data_pool = Rc::new(RefCell::new(data_pool)); // SideBar Component let sidebar = SideBarModel::builder() - .launch(layers.clone()) - .forward(sender.input_sender(), |msg| AppMsg::Close); + .launch(None) + .forward(sender.input_sender(), |msg| match msg { + SideBarOutputMsg::QueueDraw => AppMsg::Refresh, + _ => AppMsg::Close, + }); let sidebar_sender = sidebar.sender(); @@ -239,6 +240,7 @@ impl Component for AppModel { sidebar_sender, move |model_message| match model_message { MonitorOutputMsg::Attached(new_module) => { + sidebar_sender.emit(SideBarInputMsg::Package(new_module)); AppMsg::Close } _ => AppMsg::Close, @@ -290,7 +292,7 @@ impl Component for AppModel { selected_layer: vec![], sidebar, file_pool: data_pool, - control, + // control, layers, tracker: 0, }; @@ -331,6 +333,8 @@ impl Component for AppModel { AppMsg::FileIO { typ: FileIOType::Open(data), } => self.render.emit(MonitorInputMsg::PushData(data)), + + AppMsg::Refresh => self.render.emit(MonitorInputMsg::QueueDraw), _ => {} } self.update_view(widgets, _sender); diff --git a/radar-g/src/components/monitor/messages.rs b/radar-g/src/components/monitor/messages.rs index 65a752f..1e4e90e 100644 --- a/radar-g/src/components/monitor/messages.rs +++ b/radar-g/src/components/monitor/messages.rs @@ -1,16 +1,18 @@ use crate::datapool::Value; use gi::pg::ModulePackage; -use radarg_data::Data; +use radarg_core::Data; use std::{cell::RefCell, fmt::Debug, rc::Rc}; pub enum MonitorInputMsg { PushData(Value), + QueueDraw, None, } impl Debug for MonitorInputMsg { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { + MonitorInputMsg::QueueDraw => write!(f, "MonitorInputMsg::QueueDraw"), MonitorInputMsg::PushData(data) => write!(f, "MonitorInputMsg::PushData({:?})", data), MonitorInputMsg::None => write!(f, "MonitorInputMsg::None"), } diff --git a/radar-g/src/components/monitor/monitor.rs b/radar-g/src/components/monitor/monitor.rs index e2efbd6..e84e13c 100644 --- a/radar-g/src/components/monitor/monitor.rs +++ b/radar-g/src/components/monitor/monitor.rs @@ -1,6 +1,7 @@ use super::messages::{MonitorInputMsg, MonitorOutputMsg}; use crate::predefined::color_mapper::BoundaryNorm; use crate::widgets::render::RenderConfig; +use crate::SETTING; use crate::{ widgets::dynamic_col::DynamicCol, widgets::render::{Layer, Render}, @@ -94,17 +95,22 @@ impl Component for MonitorModel { self.reset(); match message { MonitorInputMsg::PushData(data) => { - widgets.renderer.get_gi(|gi| match gi.load_data(&data) { - Ok(package) => { - info!("data load success!"); - let rc_package = Rc::new(RefCell::new(package)); - self.set_module_packages(vec![rc_package.clone()]); - sender.output(MonitorOutputMsg::Attached(rc_package)); - } - Err(err) => { - error!("Load Error, cause of {}", err); - } - }) + widgets + .renderer + .get_gi(|gi| match gi.load_data(&data, &SETTING) { + Ok(package) => { + info!("data load success!"); + let rc_package = Rc::new(RefCell::new(package)); + self.set_module_packages(vec![rc_package.clone()]); + sender.output(MonitorOutputMsg::Attached(rc_package)); + } + Err(err) => { + error!("Load Error, cause of {}", err); + } + }) + } + MonitorInputMsg::QueueDraw => { + widgets.renderer.queue_draw(); } MonitorInputMsg::None => {} _ => {} diff --git a/radar-g/src/components/sidebar/bottom_bar.rs b/radar-g/src/components/sidebar/bottom_bar.rs index 0ade008..e7cf8e7 100644 --- a/radar-g/src/components/sidebar/bottom_bar.rs +++ b/radar-g/src/components/sidebar/bottom_bar.rs @@ -1,11 +1,10 @@ use crate::actions::*; +use gi::pg::SideBarInputMsg; use gtk::prelude::*; use relm4::{ actions::traits::ActionablePlus, factory::FactoryView, gtk, prelude::*, FactorySender, }; -use super::SideBarInputMsg; - #[derive(Debug)] pub enum TestMsg { Delete, diff --git a/radar-g/src/components/sidebar/mod.rs b/radar-g/src/components/sidebar/mod.rs index a2c7b4b..78054ff 100644 --- a/radar-g/src/components/sidebar/mod.rs +++ b/radar-g/src/components/sidebar/mod.rs @@ -2,3 +2,4 @@ pub mod sidebar; pub use sidebar::*; pub mod bottom_bar; pub mod meta_data_list; +pub use gi::pg::SideBarInputMsg; diff --git a/radar-g/src/components/sidebar/sidebar.rs b/radar-g/src/components/sidebar/sidebar.rs index c562c0e..2df6abd 100644 --- a/radar-g/src/components/sidebar/sidebar.rs +++ b/radar-g/src/components/sidebar/sidebar.rs @@ -1,11 +1,14 @@ use crate::actions::*; use abi_stable::type_level::trait_marker::Hash; use chrono::{DateTime, Utc}; +use gi::pg::SideBarInputMsg; +use gi::pg::{Components, ModulePackage}; use glib_macros::clone; use gtk::glib; use gtk::prelude::WidgetExt; use gtk::prelude::*; use relm4::actions::{AccelsPlus, RelmAction}; +use relm4::RelmRemoveAllExt; use relm4::{ binding::{Binding, U8Binding}, factory::{DynamicIndex, FactoryComponent, FactorySender, FactoryVecDeque}, @@ -28,34 +31,20 @@ use super::{ }; pub struct SideBarModel { - layers: Rc>>, - selected_layer_idx: usize, - counter: u8, - list_view_wrapper: TypedListView, - bottom_bar_vec: FactoryVecDeque, - meta_list_view: TypedColumnView, -} - -#[derive(Debug)] -pub enum SideBarInputMsg { - AddMetaItems(HashMap), - ClearMetaItems, - RefreshList, - None, + components: Option, } #[derive(Debug)] pub enum SideBarOutputMsg { - SelectLayer(Vec), - NewLayer(Layer), - SwitchToTimeSeries(usize), + QueueDraw, } #[relm4::component(pub)] -impl SimpleComponent for SideBarModel { - type Init = Rc>>; +impl Component for SideBarModel { + type Init = Option; type Output = SideBarOutputMsg; type Input = SideBarInputMsg; + type CommandOutput = (); view! { #[root] @@ -64,64 +53,10 @@ impl SimpleComponent for SideBarModel { set_spacing: 5, set_margin_all: 5, - gtk::Paned{ - set_orientation: gtk::Orientation::Vertical, - set_position: 200, - #[wrap(Some)] - set_start_child = >k::Box{ - set_orientation: gtk::Orientation::Vertical, - set_spacing: 5, - gtk::Frame{ - add_css_class: "rb", - #[name="meta_panel"] - gtk::Notebook::builder().vexpand(true).hexpand(true).build() -> gtk::Notebook{} - }, - }, + #[name="container"] + gtk::Box {} + }, - #[wrap(Some)] - set_end_child=>k::Box{ - set_orientation: gtk::Orientation::Vertical, - set_vexpand: true, - set_hexpand: true, - #[name="bottom_panel"] - gtk::Notebook::builder().vexpand(true).build() -> gtk::Notebook{ - set_margin_top: 10, - set_margin_bottom: 5 - }, - #[local_ref] - counter_box -> gtk::Box{ - set_spacing: 5, - } - } - } - }, - layer_page = gtk::ScrolledWindow::builder() - .vexpand(true) - .hexpand(true) - .build() -> gtk::ScrolledWindow{ - #[wrap(Some)] - #[local_ref] - set_child=my_view -> gtk::ListView{ - }, - set_margin_horizontal:5, - set_margin_vertical:3 - }, - #[local_ref] - meta_view -> gtk::ColumnView{ - set_hexpand:true, - set_vexpand:true, - set_show_column_separators: true, - set_show_row_separators: true, - set_enable_rubberband:true, - set_reorderable:false, - }, - bottom_panel.append_page(&layer_page, Some(>k::Label::new(Some("Layers")))), - meta_panel.append_page(meta_view, Some(>k::Label::new(Some("Meta")))), - // meta_panel.append_page(&Chart::new(), Some(>k::Label::new(Some("Chart")))), - #[local_ref] - info_c -> gtk::ColumnViewColumn{ - set_expand: true - } } fn init( @@ -129,274 +64,40 @@ impl SimpleComponent for SideBarModel { root: Self::Root, sender: ComponentSender, ) -> ComponentParts { - // Initialize the ListView wrapper - let mut list_view_wrapper: TypedListView = - TypedListView::with_sorting(); - - list_view_wrapper.selection_model.connect_selection_changed( - clone!(@strong sender => move |s,_, _| { - let selection = s.selection(); - - let (iter, first) = gtk::BitsetIter::init_first(&selection).unwrap(); - let mut result = vec![first as usize]; - result.extend(iter.map(|v| v as usize)); - sender.output(SideBarOutputMsg::SelectLayer(result)); - }), - ); - // let mut bottom_bar_vec = FactoryVecDeque::new(gtk::Box::default(), sender.input_sender()); - - let mut bottom_bar_vec = - FactoryVecDeque::builder() - .launch_default() - .forward(sender.input_sender(), |msg| match msg { - _ => SideBarInputMsg::None, - }); - let app = relm4::main_application(); - - { - let mut bottom_bar_vec_guard = bottom_bar_vec.guard(); - bottom_bar_vec_guard.push_back(BottomBarModel::new("add-filled".to_string())); - bottom_bar_vec_guard.push_back(BottomBarModel::new("delete-filled".to_string())); - bottom_bar_vec_guard.push_back(BottomBarModel::new("chevron-up-filled".to_string())); - bottom_bar_vec_guard.push_back(BottomBarModel::new("chevron-down-filled".to_string())); - } - let mut meta_list_view = TypedColumnView::new(); - meta_list_view.append_column::(); - meta_list_view.append_column::(); - - let mut model = SideBarModel { - meta_list_view, - layers: init, - selected_layer_idx: 0, - counter: 0, - list_view_wrapper, - bottom_bar_vec, - }; - let my_view = &model.list_view_wrapper.view; - let counter_box = model.bottom_bar_vec.widget(); - let meta_view = &model.meta_list_view.view; - let columns = model.meta_list_view.get_columns(); - let info_c = columns.get("info").unwrap(); + let mut model = SideBarModel { components: None }; let widgets = view_output!(); - - { - let mut list = model - .layers - .borrow() - .iter() - .enumerate() - .map(|(idx, v)| { - LayerItem::new( - idx as u32, - v.name.clone(), - v.visiable, - None, - LayerStatus::Instance, - ) - }) - .collect::>(); - model.list_view_wrapper.extend_from_iter(list); - } - ComponentParts { model, widgets } } - fn update(&mut self, message: Self::Input, sender: ComponentSender) { + fn update_with_view( + &mut self, + widgets: &mut Self::Widgets, + message: Self::Input, + sender: ComponentSender, + root: &Self::Root, + ) { match message { - SideBarInputMsg::RefreshList => { - let mut list = self - .layers - .borrow() - .iter() - .enumerate() - .map(|(idx, v)| { - LayerItem::new( - idx as u32, - v.name.clone(), - v.visiable, - None, - LayerStatus::Instance, // match v.get_associated_element() { - // // AssoElement::TimeSeries(_) => LayerStatus::BindToTime(Utc::now()), - // // AssoElement::Instant(_) => LayerStatus::Instance, - // _ => LayerStatus::Instance, - // - ) - }) - .collect::>(); - self.list_view_wrapper.clear(); - self.list_view_wrapper.extend_from_iter(list); + SideBarInputMsg::Package(package) => { + let package = package.borrow(); + let input_sender = sender.input_sender(); + let components = package + .component_builder() + .build(&package, root, input_sender); + + self.components = Some(components); + + widgets.container.remove_all(); + widgets + .container + .append(&self.components.as_ref().unwrap().widget()); } - SideBarInputMsg::AddMetaItems(hs) => { - for (k, v) in hs { - self.meta_list_view.append(MyListItem::new(k, v)); - } - } - SideBarInputMsg::ClearMetaItems => { - self.meta_list_view.clear(); + + SideBarInputMsg::Refresh => { + sender.output(SideBarOutputMsg::QueueDraw).unwrap(); } + _ => {} } } } - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] -enum LayerStatus { - BindToTime(DateTime), - Instance, - BindToOtherLayer(usize), -} - -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)] -struct LayerItem { - key: u32, - layer_name: String, - visiable: bool, - status: LayerStatus, - img: Option, -} - -impl LayerItem { - fn new( - key: u32, - name: String, - visiable: bool, - img: Option, - status: LayerStatus, - ) -> Self { - Self { - key, - layer_name: name, - visiable, - status, - img, - } - } -} - -struct Widgets { - label: gtk::EditableLabel, - screen_shot: gtk::Image, - status_icon: gtk::Image, - status_label: gtk::Label, - visible: gtk::Button, - opacity: gtk::Label, - menu: gtk::Popover, -} - -impl RelmListItem for LayerItem { - type Root = gtk::Box; - type Widgets = Widgets; - - fn setup(_item: >k::ListItem) -> (gtk::Box, Widgets) { - let position = _item.position() as u8; - - relm4::menu! { - main_menu: { - custom: "MyWidget", - "Remove" => RemoveLayerAction, - section!{ - "test" => RemoveLayerAction, - "select" => AddLayerAction - } - } - } - - relm4::view! { - my_box = gtk::Box { - set_valign: gtk::Align::Center, - gtk::Frame{ - set_margin_end: 10, - #[name = "screen_shot"] - gtk::Image{ - set_size_request: (65, 40), - } - }, - gtk::Grid{ - set_row_homogeneous: true, - attach[0,0,1,1] = >k::Box{ - #[name="status_icon"] - gtk::Image{ - inline_css: "-gtk-icon-transform: scale(0.8);", - }, - #[name="status_label"] - gtk::Label{ - add_css_class:"tooltip", - set_halign: gtk::Align::Start, - } - }, - #[name="label"] - attach[0,1,1,1] = >k::EditableLabel{ - set_hexpand: true, - }, - #[name="opacity"] - attach[0,2,1,1] = >k::Label{ - add_css_class:"tooltip", - set_halign: gtk::Align::Start - }, - }, - #[name="visible"] - gtk::Button{ - set_vexpand: false, - set_hexpand: false, - }, - #[name = "menu"] - gtk::Popover{} - } - } - - let widgets = Widgets { - screen_shot, - label, - status_icon, - status_label, - opacity, - visible, - menu, - }; - - (my_box, widgets) - } - - fn bind(&mut self, widgets: &mut Self::Widgets, _root: &mut Self::Root) { - let Widgets { - label, - visible, - screen_shot, - status_label, - status_icon, - opacity, - menu, - } = widgets; - - status_label.set_label(&match self.status { - LayerStatus::BindToTime(t) => format!("Bind To Time: {}", t), - LayerStatus::Instance => "Instance".to_string(), - LayerStatus::BindToOtherLayer(idx) => format!("Bind To Layer: {}", idx), - }); - - status_icon.set_icon_name(Some(match self.status { - LayerStatus::BindToTime(_) => "timer-filled", - LayerStatus::Instance => "timer-filled", - LayerStatus::BindToOtherLayer(_) => "timer-filled", - })); - - opacity.set_markup(&format!("Opacity: 0.5")); - - let gesture_click = gtk::GestureClick::new(); - gesture_click.set_button(gtk::gdk::BUTTON_SECONDARY); - screen_shot.set_paintable(self.img.as_ref()); - - let menu = menu.clone(); - gesture_click.connect_released(clone!(@weak menu => move |gesture_click, _, x, y| { - menu.set_pointing_to(Some(>k::gdk::Rectangle::new(x as i32, y as i32, 1, 1))); - menu.popup(); - })); - - visible.set_icon_name("eye-filled"); - - _root.add_controller(gesture_click); - label.set_text(&self.layer_name); - // button.set_active(self.visiable); - } -} diff --git a/radar-g/src/config.rs b/radar-g/src/config.rs deleted file mode 100644 index 2f582e8..0000000 --- a/radar-g/src/config.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::errors::ConfigError; -use crate::predefined::color_mapper::{ - BoundaryNorm, BoundaryNormDiscrete, ColorMapper, ColorMapperComb, Discrete, -}; - -use dirs; -use gtk::ResponseType::No; -use num_traits::{AsPrimitive, FromPrimitive}; -use serde::{Deserialize, Serialize}; -use std::fmt::Debug; -use std::{collections::HashMap, env, io::Write, path::PathBuf}; -use toml; diff --git a/radar-g/src/datapool/mod.rs b/radar-g/src/datapool/mod.rs index 5df11e1..cb8c8d8 100644 --- a/radar-g/src/datapool/mod.rs +++ b/radar-g/src/datapool/mod.rs @@ -1,7 +1,7 @@ -use crate::errors::DataError; use crate::PLUGIN_MANAGER; use quick_cache::sync::Cache; -use radarg_data::Data; +use radarg_core::errors::DataError; +use radarg_core::Data; use std::fmt::Display; use std::ops::Deref; use std::path::PathBuf; diff --git a/radar-g/src/main.rs b/radar-g/src/main.rs index 3e7eaba..e349b58 100644 --- a/radar-g/src/main.rs +++ b/radar-g/src/main.rs @@ -10,20 +10,17 @@ use std::{ptr, sync::Mutex}; use tokio::runtime::Runtime; mod actions; mod components; -mod config; mod datapool; -mod errors; mod plugin_system; use crate::components::app::AppMsg; use components::app::AppModel; +use gi::{App as GI, Helper, GL}; use once_cell::{sync::Lazy as SafeLazy, unsync::Lazy as UnsafeLazy}; use relm4::RelmApp; use surfman::declare_surfman; use tracing::info; use tracing_subscriber; -use gi::{App as GI, Helper, GL}; - mod predefined; mod widgets; @@ -33,10 +30,13 @@ const APP_ID: &str = "org.tsuki.radar_g"; static RUNTIME: SafeLazy = SafeLazy::new(|| Runtime::new().expect("Setting up tokio runtime needs to succeed.")); static PLUGIN_MANAGER: SafeLazy = SafeLazy::new(|| PluginManager::new().unwrap()); +static SETTING: SafeLazy = + SafeLazy::new(|| radarg_core::config::Setting::new()); fn main() { // Load GL pointers from epoxy (GL context management library used by GTK). tracing_subscriber::fmt::init(); + { #[cfg(target_os = "macos")] let library = diff --git a/radar-g/src/plugin_system/mod.rs b/radar-g/src/plugin_system/mod.rs index bcd56c2..e3c2097 100644 --- a/radar-g/src/plugin_system/mod.rs +++ b/radar-g/src/plugin_system/mod.rs @@ -1,5 +1,3 @@ -mod utils; -use crate::errors::DataError; use abi_stable::{ external_types::crossbeam_channel::{self, RReceiver, RSender}, library::{lib_header_from_path, LibraryError, LibrarySuffix, RawLibrary}, @@ -7,7 +5,8 @@ use abi_stable::{ std_types::{RBox, RErr, ROk, RResult, RSome, RStr, RString, RVec}, }; use core_extensions::*; -use radarg_data::Data; +use radarg_core::errors::DataError; +use radarg_core::Data; use radarg_plugin_interface::{DataLoaderPlugin, DataLoaderPlugin_TO, PluginId, PluginMod_Ref}; use std::{ collections::{HashMap, VecDeque}, diff --git a/radar-g/src/predefined/mod.rs b/radar-g/src/predefined/mod.rs index 27d7a1e..31be470 100644 --- a/radar-g/src/predefined/mod.rs +++ b/radar-g/src/predefined/mod.rs @@ -1,5 +1,2 @@ -pub mod map_tile; -// pub mod grid_field_renderer; -// pub mod layers; pub mod color_mapper; -pub mod widgets; +pub mod map_tile; diff --git a/radar-g/src/predefined/widgets.rs b/radar-g/src/predefined/widgets.rs deleted file mode 100644 index 28f4571..0000000 --- a/radar-g/src/predefined/widgets.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::predefined::color_mapper::ColorMapper; -use crate::widgets::Layer; -use femtovg::{renderer::OpenGl, Canvas, Color, Paint, Path}; -use num_traits::*; -use std::any::Any; -use topojson::Arc; - -#[derive(Debug)] -pub struct ColorBar { - padding: [f32; 4], - width: f32, - height: f32, - margin: [i32; 4], -} - -impl ColorBar { - pub fn new(padding: [f32; 4], size: (f32, f32), margin: [i32; 4]) -> Self { - Self { - padding, - width: size.0, - height: size.1, - margin, - } - } -} diff --git a/radar-g/src/widgets/render/imp.rs b/radar-g/src/widgets/render/imp.rs index ba201a2..83aee86 100644 --- a/radar-g/src/widgets/render/imp.rs +++ b/radar-g/src/widgets/render/imp.rs @@ -5,6 +5,7 @@ use femtovg::{Canvas, Color, FontId, Paint, Renderer}; use gi::graphics::transforms::plane::PlaneTrans; use gi::pg::layout_type::ViewPort; use gi::pg::ModulePackage; +use gi::ui::io::IO; use gi::ui::operation::Operation; use gi::{App as GI, Helper, GL}; use glow::HasContext; @@ -59,6 +60,7 @@ pub struct Render { range_changing: Cell, #[property(get, set)] scale: Cell, + pub(super) io: RefCell, pub(super) opeartion: RefCell>, pub(super) exterior: RefCell, pub(super) interior: RefCell, @@ -81,6 +83,7 @@ impl Default for Render { 0.1, 1000.0, )), + io: RefCell::new(IO::default()), range_changing: Cell::new(0.0), render_status: Cell::new(0), exterior: RefCell::new(ExteriorWidget::default()), @@ -167,10 +170,14 @@ impl GLAreaImpl for Render { } if let Some(gi) = gi.as_mut() { + let mut operation = self.opeartion.borrow_mut(); + let viewport = self.viewport.borrow(); + operation.deal_io(&viewport.as_ref().unwrap(), &self.io.borrow()); + gi.render( &mut *self.modules.borrow_mut(), - &*self.opeartion.borrow(), - self.viewport.borrow().as_ref().unwrap(), + &mut operation, + &viewport.as_ref().unwrap(), ); } @@ -248,6 +255,11 @@ impl Render { )) } + pub(super) fn set_io(&self, mut f: F) { + let mut io = self.io.borrow_mut(); + f(&mut io); + } + fn pointer_loc(&self) -> (f32, f32) { let (x, y) = self.status.borrow().pointer_location.clone(); let (_, h) = self.window_size().unwrap(); diff --git a/radar-g/src/widgets/render/interior/layers.rs b/radar-g/src/widgets/render/interior/layers.rs index 6950819..20726d0 100644 --- a/radar-g/src/widgets/render/interior/layers.rs +++ b/radar-g/src/widgets/render/interior/layers.rs @@ -1,7 +1,7 @@ use super::super::Render; -use crate::errors::PipelineError; use crate::RUNTIME; use femtovg::{renderer::OpenGl, Canvas}; +use radarg_core::errors::PipelineError; use std::cell::RefCell; use std::rc::Rc; use std::{ diff --git a/radar-g/src/widgets/render/mod.rs b/radar-g/src/widgets/render/mod.rs index 75dd574..79163af 100644 --- a/radar-g/src/widgets/render/mod.rs +++ b/radar-g/src/widgets/render/mod.rs @@ -9,7 +9,6 @@ pub mod predefined; pub mod renders; pub use self::imp::{RenderConfig, RenderMotion, RenderStatus}; -use crate::errors::PipelineError; use adw::prelude::{GLAreaExt, GestureDragExt}; use femtovg::ImageFlags; use geo_types::LineString; @@ -17,6 +16,7 @@ use gtk::prelude::*; use gtk::subclass::prelude::ObjectSubclassIsExt; use gtk::EventControllerScrollFlags; pub use interior::*; +use radarg_core::errors::PipelineError; use std::cell::{Ref, RefCell, RefMut}; use std::rc::Rc; use std::sync::{Arc, Mutex}; @@ -43,15 +43,80 @@ impl Render { let dpi = this.scale_factor() as f32; let pointer_location_detecture = gtk::EventControllerMotion::new(); + + let dpi = this.scale_factor() as f32; + pointer_location_detecture.connect_motion(clone!( + #[weak] + this, + move |_, x, y| { + let hgt = this.height() as f32; + this.imp().set_io(|io| { + io.mouse.position = [x as f32 * dpi, hgt - y as f32 * dpi]; + }); + } + )); + let scale_detecture = gtk::EventControllerScroll::new(EventControllerScrollFlags::VERTICAL); + + scale_detecture.connect_scroll(clone!( + #[strong] + this, + move |_, x, y| { + this.imp().set_io(|io| { + io.mouse.wheel_delta = y as f32; + }); + this.queue_draw(); + glib::Propagation::Proceed + } + )); + let drag_detecture = gtk::GestureDrag::new(); + drag_detecture.connect_drag_begin(clone!( + #[weak] + this, + move |slf, _, _| { + let (ox, oy) = slf.offset().unwrap_or((0.0, 0.0)); + let (ox, oy) = (ox as f32 * dpi, oy as f32 * dpi); + + let hgt = this.height() as f32; + this.imp().set_io(|io| { + io.mouse.drag_sum = [ox, -oy]; + io.mouse.drag_delta = Some([ox, -oy]); + io.mouse.is_dragging = true; + }); + this.queue_draw(); + } + )); + + drag_detecture.connect_drag_update(clone!( + #[weak] + this, + move |slf, _, _| { + let (ox, oy) = slf.offset().unwrap_or((0.0, 0.0)); + let (ox, oy) = (ox as f32 * dpi, oy as f32 * dpi); + + this.imp().set_io(|io| { + let last_drag_sum = io.mouse.drag_sum; + io.mouse.drag_delta = Some([ox - last_drag_sum[0], -oy - last_drag_sum[1]]); + io.mouse.drag_sum = [ox, -oy]; + }); + + this.queue_draw(); + } + )); + drag_detecture.connect_drag_end(clone!( #[weak] this, move |slf, _, _| { - let (ox, oy) = slf.offset().unwrap_or((0.0, 0.0)); - println!("drag_update: {:?}", (ox, oy)); + this.imp().set_io(|io| { + io.mouse.drag_sum = [0.0, 0.0]; + io.mouse.drag_delta = None; + io.mouse.is_dragging = false; + }); + + this.queue_draw(); } )); diff --git a/radarg_core/Cargo.toml b/radarg_core/Cargo.toml new file mode 100644 index 0000000..a8678ca --- /dev/null +++ b/radarg_core/Cargo.toml @@ -0,0 +1,21 @@ +[package] +edition = "2021" +name = "radarg_core" +version = "0.1.0" + +[dependencies] +chrono = "0.4.38" +ndarray = "0.16.1" +thiserror = "1.0.56" +rust-embed = "8.5.0" +toml = "0.8.19" +proj-sys = "0.23.1" +proj = "0.27.2" +dirs = "5.0.1" +num-traits = "0.2.19" +serde = { version = "1.0.209", features = ["derive"] } +relm4 = { version = "0.9.0", features = ["libadwaita"] } + +[dependencies.radarg_plugin_interface] +version = "0.1" +path = "../radarg_plugin_interface" diff --git a/gi/src/setting.rs b/radarg_core/src/config.rs similarity index 67% rename from gi/src/setting.rs rename to radarg_core/src/config.rs index 9d742ed..7484440 100644 --- a/gi/src/setting.rs +++ b/radarg_core/src/config.rs @@ -1,13 +1,12 @@ -use crate::errors::*; -use radarg_data::ProbeDataType; -use serde::{Deserialize, Serialize}; -use std::{ - env, - fs::{read, read_to_string}, - io::Write, -}; - +use crate::errors::ConfigError; +use crate::radarg_data::ProbeDataType; use crate::utils::color_tools::hex_to_rgba_u8; +use crate::Asset; +use dirs; +use num_traits::{AsPrimitive, FromPrimitive}; +use serde::{Deserialize, Serialize}; +use std::env; +use toml; macro_rules! find_cmap { ($c:ident,$find_on:ident,$({$b:tt => $name:literal}),*) => { @@ -16,7 +15,7 @@ macro_rules! find_cmap { let mut cmap = None; match $c { $( - ProbeDataType::$b => { + $b => { let find_v = $find_on.iter().find(|cb| cb.type_name == $name).map(|cb| cb); cmap = find_v; } @@ -31,41 +30,44 @@ macro_rules! find_cmap { } #[derive(Deserialize, Serialize)] + pub struct Setting { pub cmap: Vec, } impl Setting { + pub fn new() -> Self { + use std::fs::{read, read_to_string}; + use std::io::*; + let current_dir = env::current_dir().unwrap(); + + if !current_dir.join("config.toml").exists() { + let default_config = Asset::get("config.toml").unwrap(); + + let mut folder_path = current_dir.clone(); + let mut conf = folder_path.join("config.toml"); + + let mut file = std::fs::File::create_new(&conf).unwrap(); + file.write_all(&default_config.data).unwrap(); + } + + let file = read_to_string(current_dir.join("config.toml")).unwrap(); + let setting: Setting = toml::from_str(&file).unwrap(); + setting + } + pub fn find(&self, name: &ProbeDataType) -> Option<&CB> { let cmap = &self.cmap; + use ProbeDataType::*; find_cmap!( name, cmap, {DBZ => "DBZ"}, + {V => "VEL"}, {VIL => "VIL"} ) } } -impl Setting { - pub fn new() -> Self { - let current_dir = env::current_dir().unwrap(); - - // if !current_dir.join("radar.toml").exists() { - // let default_config = Asset::get("radar.toml").unwrap(); - - // let mut folder_path = current_dir.clone(); - // let mut conf = folder_path.join("radar.toml"); - - // let mut file = std::fs::File::create_new(&conf).unwrap(); - // file.write_all(&default_config.data).unwrap(); - // } - - let file = read_to_string(current_dir.join("radar.toml")).unwrap(); - let setting: Setting = toml::from_str(&file).unwrap(); - setting - } -} - #[derive(Deserialize, Serialize)] pub struct CB { #[serde(rename = "type")] @@ -83,9 +85,11 @@ impl CB { range } - pub fn color(&self) -> Result> { + pub fn color(&self) -> Result, ConfigError> { if self.colors.len() != self.levels.len() - 1 { - return Err(Error::SettingError("Color and level mismatch".to_string())); + return Err(ConfigError::FormatError( + "The number of colors and levels are not matched".to_string(), + )); } let mut result = self @@ -93,7 +97,7 @@ impl CB { .iter() .map(|v| hex_to_rgba_u8(v)) .collect::, String>>() - .map_err(|v| Error::SettingError(v.to_string()))?; + .map_err(|v| ConfigError::FormatError(v.to_string()))?; let mut span = Vec::with_capacity(self.levels.len() - 1); diff --git a/radar-g/src/errors.rs b/radarg_core/src/errors.rs similarity index 84% rename from radar-g/src/errors.rs rename to radarg_core/src/errors.rs index 7300890..1ea75d2 100644 --- a/radar-g/src/errors.rs +++ b/radarg_core/src/errors.rs @@ -33,6 +33,8 @@ pub enum ConfigError { VarError(#[from] std::env::VarError), #[error("Can't find and create default Config")] DefaultConfigError, + #[error("Format Error, {0}")] + FormatError(String), } #[derive(Debug, Error)] @@ -44,13 +46,3 @@ pub enum PoolError { #[error("Data Pool is not initialized")] PoolInitialized(&'static str), } - -#[derive(Debug, Error)] -pub enum RenderError { - #[error("")] - PreRenderError(#[from] femtovg::ErrorKind), - #[error("")] - None, - #[error("Canceled")] - Canceled, -} diff --git a/radarg_core/src/lib.rs b/radarg_core/src/lib.rs new file mode 100644 index 0000000..79c879d --- /dev/null +++ b/radarg_core/src/lib.rs @@ -0,0 +1,12 @@ +pub mod config; +pub mod errors; +pub mod radarg_data; +use rust_embed::RustEmbed; +pub mod utils; +pub mod widget_interface; + +#[derive(RustEmbed)] +#[folder = "statics/"] +pub struct Asset; + +pub use radarg_data::*; diff --git a/radarg_data/src/lib.rs b/radarg_core/src/radarg_data/mod.rs similarity index 100% rename from radarg_data/src/lib.rs rename to radarg_core/src/radarg_data/mod.rs diff --git a/radarg_core/src/utils/color_tools.rs b/radarg_core/src/utils/color_tools.rs new file mode 100644 index 0000000..afc5bb4 --- /dev/null +++ b/radarg_core/src/utils/color_tools.rs @@ -0,0 +1,18 @@ +pub fn hex_to_rgba_u8(hex: &str) -> Result<[u8; 4], String> { + let hex = hex.trim_start_matches('#'); + + if hex.len() != 6 && hex.len() != 8 { + return Err("Hex color should be in #RRGGBB or #RRGGBBAA format".to_string()); + } + + let r = u8::from_str_radix(&hex[0..2], 16).map_err(|e| e.to_string())?; + let g = u8::from_str_radix(&hex[2..4], 16).map_err(|e| e.to_string())?; + let b = u8::from_str_radix(&hex[4..6], 16).map_err(|e| e.to_string())?; + let a = if hex.len() == 8 { + u8::from_str_radix(&hex[6..8], 16).map_err(|e| e.to_string())? + } else { + 255 // 默认不透明 + }; + + Ok([r, g, b, a]) +} diff --git a/radarg_core/src/utils/mod.rs b/radarg_core/src/utils/mod.rs new file mode 100644 index 0000000..73e9284 --- /dev/null +++ b/radarg_core/src/utils/mod.rs @@ -0,0 +1 @@ +pub mod color_tools; diff --git a/radar-g/src/plugin_system/utils.rs b/radarg_core/src/widget_interface.rs similarity index 100% rename from radar-g/src/plugin_system/utils.rs rename to radarg_core/src/widget_interface.rs diff --git a/radarg_core/statics/config.toml b/radarg_core/statics/config.toml new file mode 100644 index 0000000..971cab0 --- /dev/null +++ b/radarg_core/statics/config.toml @@ -0,0 +1,217 @@ +[[cmap]] +type = "DBZ" +levels = [0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75] +colors = [ + "#aaaaaa", + "#0022ff", + "#01a0f6", + "#00ecec", + "#00d800", + "#019000", + "#ffff00", + "#e7c000", + "#ff9000", + "#ff0000", + "#d60000", + "#c00000", + "#ff00f0", + "#9600b4", + "#ad90f0", +] + +[[cmap]] +type = "VEL" +levels = [ + -90, + -45, + -35, + -27, + -20, + -15, + -10, + -5, + -1, + 0, + 1, + 5, + 10, + 15, + 20, + 27, + 1000, +] +colors = [ + "#9fffff", + "#00e0ff", + "#0080ff", + "#320096", + "#00fb90", + "#00bb90", + "#008f00", + "#cdc09f", + "#000000", + "#f88700", + "#ffcf00", + "#ffff00", + "#ae0000", + "#d07000", + "#dd0000", + "#ff0000", +] + +[[cmap]] +type = "SW" +colors = [ + "#E0E0E0", + "#7CE0E0", + "#00E0E0", + "#00B0B0", + "#00FEFE", + "#00C400", + "#008000", + "#FEFE00", + "#FED200", + "#FE7C00", + "#FEB0B0", + "#FE5858", + "#FE0000", + "#FEFEFE", +] +levels = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] + +[[cmap]] +type = "CC" +colors = [ + "#003CFF", + "#00EFEF", + "#00BABF", + "#00837D", + "#008938", + "#00B729", + "#00DA0D", + "#00FF00", + "#FFFF3B", + "#FFF000", + "#FFC600", + "#FFA500", + "#FF7200", + "#FF1F00", + "#C10000", + "#D400AA", +] +levels = [ + 0, + 0.1, + 0.3, + 0.5, + 0.6, + 0.7, + 0.8, + 0.85, + 0.9, + 0.92, + 0.94, + 0.95, + 0.96, + 0.97, + 0.98, + 0.99, +] + +[[cmap]] +type = "KDP" +colors = [ + "#00FFFF", + "#00EFEF", + "#00A8AC", + "#B4B4B4", + "#B4B4B4", + "#00C027", + "#00E80A", + "#24FF24", + "#FFFF1E", + "#FFE600", + "#FFBC00", + "#FF9800", + "#FF5E00", + "#F20F00", + "#BB003A", + "#DD009C", + "#FF00FF", +] +levels = [ + -0.8, + -0.4, + -0.2, + -0.1, + 0.1, + 0.15, + 0.22, + 0.33, + 0.5, + 0.75, + 1.1, + 1.7, + 2.4, + 3.1, + 7, + 20, +] + +[[cmap]] +type = "ZDR" +colors = [ + "#464646", + "#505050", + "#5A5A5A", + "#646464", + "#6E6E6E", + "#787878", + "#828282", + "#8C8C8C", + "#969696", + "#AFAFAF", + "#C8C8C8", + "#DCF0DC", + "#00C027", + "#00E80A", + "#24FF24", + "#FFFF1E", + "#FFF20F", + "#FFE600", + "#FFBC00", + "#FF9800", + "#FF5E00", + "#FFFF00", + "#F20F00", + "#BB003A", + "#DD009C", + "#FF00FF", +] +levels = [ + -5, + -4.5, + -4, + -3.5, + -3, + -2.5, + -2, + -1.5, + -1, + -0.5, + 0, + 0.5, + 1, + 1.5, + 2, + 2.5, + 3, + 3.5, + 4, + 4.5, + 5, + 5.5, + 6, + 6.5, + 7, +] diff --git a/radarg_data/Cargo.toml b/radarg_data/Cargo.toml deleted file mode 100644 index fb2e55a..0000000 --- a/radarg_data/Cargo.toml +++ /dev/null @@ -1,14 +0,0 @@ -[package] -name = "radarg_data" -version = "0.1.0" -authors = ["tsuki "] -edition = "2021" - -[dependencies] -chrono = "0.4.38" -ndarray = "0.16.1" -thiserror = "1.0.56" - -[dependencies.radarg_plugin_interface] -version = "0.1" -path = "../radarg_plugin_interface" diff --git a/test2.npz b/test2.npz deleted file mode 100644 index a142803..0000000 Binary files a/test2.npz and /dev/null differ