rebuild factor
This commit is contained in:
parent
6ceebdd7f4
commit
3a9f0dcaa3
10
.dir-locals.el
Normal file
10
.dir-locals.el
Normal file
@ -0,0 +1,10 @@
|
||||
((nil . ((eval . (progn
|
||||
;; radar_g 调试配置
|
||||
(dap-register-debug-template
|
||||
"radar_g::LLDB"
|
||||
(list :type "lldb"
|
||||
:request "launch"
|
||||
:name "radar_g::LLDB"
|
||||
:gdbpath "~/.cargo/bin/rust-lldb"
|
||||
:program "${workspaceFolder}/target/debug/cinrad_g"
|
||||
:cwd "${workspaceFolder}"))
|
||||
18
Cargo.lock
generated
18
Cargo.lock
generated
@ -779,7 +779,7 @@ dependencies = [
|
||||
"proj",
|
||||
"proj-sys",
|
||||
"quadtree_rs",
|
||||
"quick_cache",
|
||||
"quick_cache 0.4.3",
|
||||
"radarg_core",
|
||||
"radarg_plugin_interface",
|
||||
"rayon",
|
||||
@ -1838,6 +1838,7 @@ dependencies = [
|
||||
"nom",
|
||||
"nom-derive",
|
||||
"once_cell",
|
||||
"paste 1.0.15",
|
||||
"pathfinder_geometry",
|
||||
"radarg_core",
|
||||
"raw-window-handle",
|
||||
@ -4159,6 +4160,18 @@ dependencies = [
|
||||
"parking_lot",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick_cache"
|
||||
version = "0.6.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27a893a83255c587d31137bc7e350387b49267b0deac44120fd8fa8bd0d61645"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
"parking_lot",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.13"
|
||||
@ -4181,12 +4194,15 @@ dependencies = [
|
||||
name = "radarg_core"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"abi_stable",
|
||||
"chrono",
|
||||
"core_extensions",
|
||||
"dirs",
|
||||
"ndarray 0.16.1",
|
||||
"num-traits",
|
||||
"proj",
|
||||
"proj-sys",
|
||||
"quick_cache 0.6.5",
|
||||
"radarg_plugin_interface",
|
||||
"relm4",
|
||||
"rust-embed",
|
||||
|
||||
@ -43,6 +43,7 @@ femtovg = "0.9.2"
|
||||
rust-embed = "8.5.0"
|
||||
tempfile = "3.12.0"
|
||||
relm4 = { version = "0.9.0", features = ["libadwaita"] }
|
||||
paste = "1.0.15"
|
||||
|
||||
[features]
|
||||
default = ["sdf_font"]
|
||||
|
||||
@ -13,8 +13,8 @@ pub enum Error {
|
||||
#[error("Invalid Program {0}")]
|
||||
InvalidProgram(String),
|
||||
|
||||
#[error("Invalid CoordType")]
|
||||
InvalidDataType,
|
||||
#[error("Error: {0}")]
|
||||
InvalidDataType(String),
|
||||
|
||||
#[error("Init Error, cause of {0}")]
|
||||
InitError(anyhow::Error),
|
||||
|
||||
@ -106,14 +106,14 @@ impl Graphics for AggFastPath {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mount(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
fn mount(&self, gl: &glow::Context) -> Result<()> {
|
||||
unsafe {
|
||||
gl.use_program(self.program.native_program);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unmount(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
fn unmount(&self, gl: &glow::Context) -> Result<()> {
|
||||
unsafe {
|
||||
gl.use_program(None);
|
||||
}
|
||||
|
||||
@ -33,7 +33,7 @@ pub trait Graphics {
|
||||
|
||||
fn program_mut(&mut self) -> &mut Program;
|
||||
|
||||
fn mount(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
fn mount(&self, gl: &glow::Context) -> Result<()> {
|
||||
unsafe {
|
||||
gl.use_program(self.program_ref().native_program.clone());
|
||||
}
|
||||
@ -41,7 +41,7 @@ pub trait Graphics {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unmount(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
fn unmount(&self, gl: &glow::Context) -> Result<()> {
|
||||
unsafe {
|
||||
gl.use_program(None);
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ impl PPI {
|
||||
|
||||
pub fn data_info(&self, data: &RadarGridData) -> Result<(f32, f32, ProbeDataType, usize, f32)> {
|
||||
if data.coord_type().is_none() {
|
||||
return Err(Error::InvalidDataType);
|
||||
return Err(Error::InvalidDataType(format!("Invalid CoordType")));
|
||||
}
|
||||
match data.coord_type().unwrap() {
|
||||
CoordType::Polar {
|
||||
@ -79,7 +79,7 @@ impl PPI {
|
||||
}
|
||||
|
||||
_ => {
|
||||
return Err(Error::InvalidDataType);
|
||||
return Err(Error::InvalidDataType(format!("Invalid CoordType")));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -163,14 +163,14 @@ impl Graphics for PPI {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn mount(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
fn mount(&self, gl: &glow::Context) -> Result<()> {
|
||||
unsafe {
|
||||
gl.use_program(self.program.native_program);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn unmount(&mut self, gl: &glow::Context) -> Result<()> {
|
||||
fn unmount(&self, gl: &glow::Context) -> Result<()> {
|
||||
unsafe {
|
||||
gl.use_program(None);
|
||||
}
|
||||
@ -216,7 +216,7 @@ impl AttaWithBuffer for PPI {
|
||||
return Ok((vertices, None, len));
|
||||
}
|
||||
_ => {
|
||||
return Err(Error::InvalidDataType);
|
||||
return Err(Error::InvalidDataType(format!("Invalid CoordType")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
use log::*;
|
||||
use radarg_core::radarg_data::Data;
|
||||
use std::{cell::RefCell, path::PathBuf, rc::Rc};
|
||||
use radarg_core::{datapool::Value, radarg_data::Data};
|
||||
use std::{cell::RefCell, collections::HashMap, path::PathBuf, rc::Rc, sync::Arc};
|
||||
|
||||
use crate::{
|
||||
errors::*,
|
||||
@ -19,7 +19,10 @@ use crate::{
|
||||
};
|
||||
use glow::HasContext;
|
||||
|
||||
use super::layout_type::{self, ViewPort};
|
||||
use super::{
|
||||
layout_type::{self, ViewPort},
|
||||
ModuleRefs,
|
||||
};
|
||||
use super::{ModulePackage, Programs};
|
||||
use crate::{font_manager::FontManager, graphics::font::Text};
|
||||
|
||||
@ -61,17 +64,12 @@ impl App {
|
||||
&mut self.context.programs
|
||||
}
|
||||
|
||||
pub fn supported_modules(&mut self) -> Vec<super::Modules> {
|
||||
self.program().supported_modules()
|
||||
pub fn supported_modules<'a>(
|
||||
&mut self,
|
||||
data: &'a Value<Data>,
|
||||
) -> HashMap<&'a Arc<Data>, Vec<ModuleRefs>> {
|
||||
self.program().supported_modules(data)
|
||||
}
|
||||
|
||||
// pub fn load_data(
|
||||
// &mut self,
|
||||
// data: &Vec<Data>,
|
||||
// setting: &radarg_core::config::Setting,
|
||||
// ) -> Result<ModulePackage> {
|
||||
// self.program().load_data(data, setting)
|
||||
// }
|
||||
}
|
||||
|
||||
pub struct Context {
|
||||
|
||||
@ -3,8 +3,11 @@ use femtovg::renderer::OpenGl;
|
||||
use femtovg::Canvas;
|
||||
use glow::HasContext;
|
||||
use layout_type::ViewPort;
|
||||
use modules::PPIModuleConfigComponent;
|
||||
use radarg_core::radarg_data::Data;
|
||||
use modules::{PPIModuleConfigComponent, PPIModuleRef};
|
||||
use radarg_core::{datapool::Value, radarg_data::Data};
|
||||
|
||||
use paste::paste;
|
||||
|
||||
use relm4::{
|
||||
gtk,
|
||||
gtk::prelude::{Cast, IsA},
|
||||
@ -14,22 +17,22 @@ use relm4::{
|
||||
pub mod layout_type;
|
||||
mod modules;
|
||||
|
||||
use crate::font_manager::FontManager;
|
||||
use crate::graphics::collections::agg_fast_path::AggFastPath;
|
||||
use crate::graphics::font::Text;
|
||||
use crate::graphics::ppi::PPI;
|
||||
use crate::graphics::threed::Trackball;
|
||||
use crate::graphics::transforms::plane::PlaneTrans;
|
||||
use crate::graphics::{AttaWithProgram, AttachWithIO};
|
||||
use crate::ui::operation::Operation;
|
||||
use crate::ui::typ::LayoutAttach;
|
||||
use crate::utils::resources::GL;
|
||||
use crate::{errors::*, graphics::Graphics};
|
||||
use crate::{
|
||||
errors::*,
|
||||
font_manager::FontManager,
|
||||
graphics::{
|
||||
collections::agg_fast_path::AggFastPath, font::Text, ppi::PPI,
|
||||
transforms::plane::PlaneTrans, AttaWithProgram, AttachWithIO, Graphics,
|
||||
},
|
||||
ui::{operation::Operation, typ::LayoutAttach},
|
||||
utils::resources::GL,
|
||||
};
|
||||
|
||||
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;
|
||||
use std::{cell::RefCell, collections::HashMap};
|
||||
use std::{rc::Rc, sync::Arc};
|
||||
|
||||
static MODULE_PACKAGE_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
@ -77,19 +80,22 @@ impl Programs {
|
||||
PPIModule::new(&self.gl, &mut self._ppi, &mut self._text, &mut self._line)
|
||||
}
|
||||
|
||||
pub fn supported_modules(&mut self) -> Vec<Modules> {
|
||||
vec![Modules::PPI(self.ppi())]
|
||||
pub fn ppi_ref(&self) -> PPIModuleRef {
|
||||
PPIModuleRef::new(&self.gl, &self._ppi, &self._text, &self._line)
|
||||
}
|
||||
|
||||
// pub fn load_data(
|
||||
// &mut self,
|
||||
// data: &Vec<Data>,
|
||||
// setting: &radarg_core::config::Setting,
|
||||
// ) -> Result<Vec<ModulePackage>> {
|
||||
// data.iter()
|
||||
// .map(|d| self.ppi().load_data(, setting).map(|v| v.into()))
|
||||
// .collect()
|
||||
// }
|
||||
pub fn supported_modules<'a>(
|
||||
&mut self,
|
||||
data: &'a Value<Data>,
|
||||
) -> HashMap<&'a Arc<Data>, Vec<ModuleRefs>> {
|
||||
let mut result = HashMap::new();
|
||||
|
||||
for (k, d) in data.iter() {
|
||||
result.insert(d, vec![ModuleRefs::PPI(self.ppi_ref())]);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn draw_modules(
|
||||
&mut self,
|
||||
@ -108,7 +114,7 @@ impl Programs {
|
||||
}
|
||||
|
||||
macro_rules! impl_module_package {
|
||||
($({$t:ty => $b: tt | $module:tt | $c: ty}),+) => {
|
||||
($({$t:ty => $b: tt | $module:tt | $module_ref:tt | $c: ty}),+) => {
|
||||
|
||||
pub enum Modules<'b, 'gl: 'b>{
|
||||
$(
|
||||
@ -116,6 +122,35 @@ macro_rules! impl_module_package {
|
||||
)+
|
||||
}
|
||||
|
||||
pub enum ModuleRefs<'b, 'gl:'b>{
|
||||
$(
|
||||
$b($module_ref<'b,'gl>)
|
||||
)+
|
||||
}
|
||||
|
||||
impl Modules<'_, '_> {
|
||||
pub fn load_data(&self, data:&Data, setting: &radarg_core::config::Setting) -> Result<ModulePackage> {
|
||||
match self {
|
||||
$(
|
||||
Modules::$b(m) => {
|
||||
let cursor = m.load_data(data.into(), setting)?;
|
||||
Ok(cursor.into())
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleRefs<'_, '_> {
|
||||
pub fn name(&self) -> &'static str {
|
||||
match self {
|
||||
$(
|
||||
ModuleRefs::$b(m) => m.name(),
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum _ModulePackage {
|
||||
$(
|
||||
@ -209,7 +244,7 @@ macro_rules! impl_module_package {
|
||||
}
|
||||
|
||||
impl_module_package!(
|
||||
{PPIPackage => PPI | PPIModule | PPIModuleConfigComponent}
|
||||
{PPIPackage => PPI | PPIModule | PPIModuleRef | PPIModuleConfigComponent}
|
||||
);
|
||||
|
||||
impl ModulePackage {
|
||||
|
||||
@ -11,10 +11,13 @@ 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};
|
||||
use std::{cell::RefCell, path::Component, rc::Rc, sync::Arc};
|
||||
mod ppi;
|
||||
use crate::errors::*;
|
||||
pub use ppi::{PPIModule, PPIModuleConfigComponent, PPIModuleConfigComponentWidgets, PPIPackage};
|
||||
pub use ppi::{
|
||||
PPIModule, PPIModuleConfigComponent, PPIModuleConfigComponentWidgets, PPIModuleRef, PPIPackage,
|
||||
};
|
||||
|
||||
use relm4::Component as RComponent;
|
||||
|
||||
use super::{layout_type::ViewPort, SideBarInputMsg};
|
||||
@ -95,6 +98,8 @@ pub trait Module: Sized {
|
||||
type Data;
|
||||
type Operation: AttachWithIO;
|
||||
|
||||
const NAME: &'static str;
|
||||
|
||||
fn render(
|
||||
&mut self,
|
||||
cursor: &mut Self::Cursor,
|
||||
@ -102,7 +107,7 @@ pub trait Module: Sized {
|
||||
viewport: &ViewPort,
|
||||
) -> Result<()>;
|
||||
|
||||
fn load_data<'dt>(&self, data: &Rc<Self::Data>, setting: &Setting) -> Result<Self::Cursor>;
|
||||
fn load_data<'dt>(&self, data: &Arc<Self::Data>, setting: &Setting) -> Result<Self::Cursor>;
|
||||
}
|
||||
|
||||
pub trait ModuleCursor {
|
||||
|
||||
@ -21,6 +21,7 @@ use glow::HasContext;
|
||||
use std::{
|
||||
cell::{RefCell, RefMut},
|
||||
rc::Rc,
|
||||
sync::Arc,
|
||||
};
|
||||
use tracker::track;
|
||||
|
||||
@ -40,6 +41,125 @@ pub struct PPIModule<'b, 'gl: 'b> {
|
||||
text_program: &'b mut Text,
|
||||
}
|
||||
|
||||
pub struct PPIModuleRef<'b, 'gl: 'b> {
|
||||
gl: &'gl GL,
|
||||
ppi_program: &'b PPI,
|
||||
line_program: &'b AggFastPath,
|
||||
text_program: &'b Text,
|
||||
}
|
||||
|
||||
impl<'b, 'a: 'b> PPIModuleRef<'b, 'a> {
|
||||
pub fn new(gl: &'a GL, ppi: &'b PPI, text: &'b Text, line: &'b AggFastPath) -> Self {
|
||||
let config = PPIConfig::default();
|
||||
Self {
|
||||
gl,
|
||||
ppi_program: ppi,
|
||||
text_program: text,
|
||||
line_program: line,
|
||||
}
|
||||
}
|
||||
|
||||
fn bind_ppi_pg(
|
||||
&self,
|
||||
attach: &mut Attach,
|
||||
data: &RadarGridData,
|
||||
config: &PPIModuleConfig,
|
||||
) -> Result<()> {
|
||||
let (vbo, ebo, len) = self
|
||||
.ppi_program
|
||||
.bake(&self.gl, data, &config.to_ppi_config())?;
|
||||
attach.bind_data(&vbo, ebo.as_ref(), len, glow::DYNAMIC_DRAW);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bind_line_pg(
|
||||
&self,
|
||||
attach: &mut Attach,
|
||||
data: &RadarGridData,
|
||||
config: &PPIModuleConfig,
|
||||
) -> Result<()> {
|
||||
let raw_config = config.to_line_config();
|
||||
|
||||
// Will be changed in the future
|
||||
let outskirt = 10.0;
|
||||
|
||||
let mut paths = vec![];
|
||||
|
||||
let range_line_num = config.range_line_num;
|
||||
let r = outskirt / range_line_num as f32;
|
||||
let seg_num = 200;
|
||||
let angle = 2f32 * f32::consts::PI / seg_num as f32;
|
||||
|
||||
for range in 1..=range_line_num {
|
||||
// Create the path
|
||||
let mut path = Path::new(true);
|
||||
let r = r * range as f32;
|
||||
// Draw the circle
|
||||
for seg in 0..seg_num {
|
||||
let angle = angle * seg as f32;
|
||||
let x = (angle.cos() * r) as f32;
|
||||
let y = (angle.sin() * r) as f32;
|
||||
path.push([x, y, 0.01]);
|
||||
}
|
||||
path.finish();
|
||||
paths.push(path);
|
||||
}
|
||||
|
||||
let ath_lin_num = config.ath_line_num;
|
||||
|
||||
let a = 2.0 * f32::consts::PI / ath_lin_num as f32;
|
||||
for _a in 0..=ath_lin_num {
|
||||
let mut path = Path::new(false);
|
||||
let x = (a * _a as f32).cos() * outskirt;
|
||||
let y = (a * _a as f32).sin() * outskirt;
|
||||
path.push([0.0, 0.0, 0.01]);
|
||||
path.push([x, y, 0.01]);
|
||||
path.finish();
|
||||
paths.push(path);
|
||||
}
|
||||
|
||||
if config.vertical_axis {
|
||||
let mut path = Path::new(false);
|
||||
path.push([0.0, 0.0, 0.0]);
|
||||
path.push([0.0, 0.0, outskirt]);
|
||||
path.finish();
|
||||
paths.push(path);
|
||||
}
|
||||
|
||||
let (vbo, ebo, len) = self.line_program.bake(&self.gl, &paths, &raw_config)?;
|
||||
attach.bind_data(&vbo, ebo.as_ref(), len, glow::STATIC_DRAW);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn bind_tick(
|
||||
&self,
|
||||
attach: &mut Attach,
|
||||
data: &RadarGridData,
|
||||
config: &PPIModuleConfig,
|
||||
) -> Result<()> {
|
||||
let font_style = config.to_font_config();
|
||||
|
||||
match font_style {
|
||||
FontConfig::Textline(line_style, font_style) => {
|
||||
let new_text = TextLine::new("Hello,World", Some(font_style), None);
|
||||
let position_text =
|
||||
PositionText::new(new_text, [0.0, 0.0, 0.0], Anchor::BottomCenter);
|
||||
let text_pg_config = config.to_font_config();
|
||||
let (vbo, ebo, len) =
|
||||
self.text_program
|
||||
.bake(&self.gl, &position_text, &text_pg_config)?;
|
||||
attach.bind_data(&vbo, ebo.as_ref(), len, glow::STATIC_DRAW);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &'static str {
|
||||
"PPI"
|
||||
}
|
||||
}
|
||||
|
||||
impl<'b, 'a: 'b> PPIModule<'b, 'a> {
|
||||
pub fn new(
|
||||
gl: &'a GL,
|
||||
@ -158,6 +278,8 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> {
|
||||
type Data = RadarGridData;
|
||||
type Operation = PlaneTrans;
|
||||
|
||||
const NAME: &'static str = "PPI";
|
||||
|
||||
fn render<'dt>(
|
||||
&mut self,
|
||||
cursor: &mut Self::Cursor,
|
||||
@ -238,7 +360,7 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn load_data<'dt>(&self, data: &Rc<Self::Data>, setting: &Setting) -> Result<Self::Cursor> {
|
||||
fn load_data<'dt>(&self, data: &Arc<Self::Data>, setting: &Setting) -> Result<Self::Cursor> {
|
||||
// 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);
|
||||
@ -246,12 +368,17 @@ impl<'b, 'a: 'b> Module for PPIModule<'b, 'a> {
|
||||
// Get the data info
|
||||
let (r, a, t, max_layer, unvalid) = self.ppi_program.data_info(&data)?;
|
||||
|
||||
println!("name: {}", data.info.value_name);
|
||||
|
||||
// Find the color map
|
||||
let cmap = setting.find(&t);
|
||||
|
||||
// Check if the color map is valid
|
||||
if cmap.is_none() {
|
||||
return Err(Error::InvalidDataType);
|
||||
return Err(Error::InvalidDataType(format!(
|
||||
"{}'s colormap is not found",
|
||||
data.info.value_name
|
||||
)));
|
||||
}
|
||||
let cmap = cmap.unwrap();
|
||||
|
||||
@ -294,7 +421,7 @@ pub struct PPIPackage {
|
||||
ppi_attach: Attach,
|
||||
line_attach: Attach,
|
||||
tick_attach: Attach,
|
||||
data: Rc<RadarGridData>,
|
||||
data: Arc<RadarGridData>,
|
||||
}
|
||||
|
||||
impl PPIPackage {
|
||||
@ -303,7 +430,7 @@ impl PPIPackage {
|
||||
ppi_attach: Attach,
|
||||
line_attach: Attach,
|
||||
tick_attach: Attach,
|
||||
data: Rc<RadarGridData>,
|
||||
data: Arc<RadarGridData>,
|
||||
) -> Self {
|
||||
Self {
|
||||
draw_helper: true,
|
||||
@ -415,35 +542,71 @@ impl SimpleComponent for PPIModuleConfigComponent {
|
||||
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::PreferencesPage {
|
||||
adw::PreferencesGroup {
|
||||
set_title:"PPI Config",
|
||||
set_hexpand: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);
|
||||
sender.output(OutputMsg::Refresh);
|
||||
}
|
||||
},
|
||||
adw::SwitchRow{
|
||||
set_title:"Three D",
|
||||
set_active: init_config.is_three_d,
|
||||
connect_active_notify[sender, config_ref] => move |this| {
|
||||
let active = this.is_active();
|
||||
config_ref.borrow_mut().set_is_three_d(active);
|
||||
sender.output(OutputMsg::Refresh);
|
||||
}
|
||||
},
|
||||
adw::SpinRow {
|
||||
set_title: "Layer",
|
||||
set_digits: 0,
|
||||
set_numeric: true,
|
||||
set_snap_to_ticks: true,
|
||||
#[wrap(Some)]
|
||||
set_adjustment=>k::Adjustment::new(
|
||||
init_config.layer as f64 + 1.0,
|
||||
1.0,
|
||||
init_config.max_layer as f64,
|
||||
1.0,
|
||||
1.0,
|
||||
1.0
|
||||
),
|
||||
connect_value_notify[sender, config_ref] => move |this| {
|
||||
let layer = this.value() as usize - 1;
|
||||
config_ref.borrow_mut().set_layer(layer);
|
||||
sender.output(OutputMsg::Refresh);
|
||||
},
|
||||
},
|
||||
},
|
||||
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);
|
||||
}
|
||||
},
|
||||
gtk::Button {
|
||||
set_label: "Refresh",
|
||||
connect_clicked[sender] => move |_| {
|
||||
sender.output(OutputMsg::Refresh);
|
||||
}
|
||||
adw::PreferencesGroup {
|
||||
set_title:"Show Config",
|
||||
set_hexpand:true,
|
||||
adw::PreferencesRow {
|
||||
set_title:"Color Line",
|
||||
#[wrap(Some)]
|
||||
set_child=>k::Box{
|
||||
gtk::ColorDialogButton {
|
||||
set_dialog=>k::ColorDialog {},
|
||||
set_rgba: >k::gdk::RGBA::new(init_config.line_color[0], init_config.line_color[1],init_config.line_color[2],init_config.line_color[3]),
|
||||
connect_rgba_notify[sender, config_ref] => move |this| {
|
||||
let rgba = this.rgba();
|
||||
let color = [rgba.red(), rgba.green(), rgba.blue(), rgba.alpha()];
|
||||
config_ref.borrow_mut().set_line_color(color);
|
||||
sender.output(OutputMsg::Refresh);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -25,3 +25,9 @@ pub struct IO {
|
||||
pub mouse: MouseIO,
|
||||
pub keyboard: KeyboardIO,
|
||||
}
|
||||
|
||||
impl IO {
|
||||
pub fn reset(&mut self) {
|
||||
self.mouse.wheel_delta = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use nom::error::Error;
|
||||
use thiserror::Error;
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ETWSError {
|
||||
@ -6,9 +7,17 @@ pub enum ETWSError {
|
||||
#[from]
|
||||
source: std::io::Error,
|
||||
},
|
||||
#[error("Format Error")]
|
||||
#[error("Unsupported Format")]
|
||||
FormatError {
|
||||
#[from]
|
||||
source: anyhow::Error,
|
||||
},
|
||||
#[error("Binary Error")]
|
||||
NomError,
|
||||
}
|
||||
|
||||
impl<'a> From<nom::Err<nom::error::Error<&'a [u8]>>> for ETWSError {
|
||||
fn from(value: nom::Err<nom::error::Error<&'a [u8]>>) -> Self {
|
||||
ETWSError::NomError
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,7 +168,7 @@ impl DataLoaderPlugin for ETWSLoader {
|
||||
{ "DBZ" | "CR" | "FR" | "R" => DBZ},
|
||||
{ "VIL" => VIL},
|
||||
{ "EB" => EB},
|
||||
{ "V" => V},
|
||||
{ "V" | "VEL" => V},
|
||||
{ "ZDR" => ZDR},
|
||||
{ "PHIDP" => PHIDP},
|
||||
{ "KDP" => KDP},
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use crate::error::ETWSError;
|
||||
use abi_stable::std_types::vec;
|
||||
use bytemuck::cast_slice;
|
||||
use nom::{
|
||||
@ -244,34 +245,84 @@ fn parse_sub_pulse_config(input: &[u8]) -> IResult<&[u8], SubPulseConfig> {
|
||||
Ok((input, sub_pulse_config))
|
||||
}
|
||||
|
||||
pub fn parse_raw_data<P: AsRef<Path>>(path: P) -> io::Result<RadarData> {
|
||||
pub fn parse_raw_data<P: AsRef<Path>>(path: P) -> Result<RadarData, ETWSError> {
|
||||
let path = path.as_ref();
|
||||
|
||||
if path.extension().is_none() {
|
||||
if path.is_file() {
|
||||
let mut file = File::open(path)?;
|
||||
let mut buf = Vec::new();
|
||||
file.read_to_end(&mut buf).unwrap();
|
||||
if &buf[0..4] == b"SSTM" || &buf[16..20] == b"STDM" || &buf[0..4] == b"RSTM" {
|
||||
return get_radar_data(buf);
|
||||
} else {
|
||||
return Err(ETWSError::FormatError {
|
||||
source: anyhow::anyhow!("Invalid file format"),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
return Err(ETWSError::IOError {
|
||||
source: io::Error::new(io::ErrorKind::NotFound, "File not found"),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if path.extension().unwrap() == "zip" {
|
||||
let file = File::open(path).unwrap();
|
||||
let mut archive = ZipArchive::new(file).unwrap();
|
||||
let mut file = archive.by_index(0).unwrap();
|
||||
|
||||
let mut buf = Vec::new();
|
||||
file.read_to_end(&mut buf).unwrap();
|
||||
file.read_to_end(&mut buf)?;
|
||||
if buf.len() < 4 {
|
||||
return Err(ETWSError::FormatError {
|
||||
source: anyhow::anyhow!("Invalid file format"),
|
||||
});
|
||||
}
|
||||
if &buf[0..4] == b"SSTM" || &buf[16..20] == b"STDM" || &buf[0..4] == b"RSTM" {
|
||||
return get_radar_data(buf);
|
||||
} else {
|
||||
panic!("Invalid file format");
|
||||
return Err(ETWSError::FormatError {
|
||||
source: anyhow::anyhow!("Invalid file format"),
|
||||
});
|
||||
}
|
||||
} else if path.extension().unwrap() == ".gz" {
|
||||
let file = File::open(path)?;
|
||||
let mut archive = flate2::read::GzDecoder::new(file);
|
||||
let mut buf = Vec::new();
|
||||
archive.read_to_end(&mut buf)?;
|
||||
if buf.len() < 4 {
|
||||
return Err(ETWSError::FormatError {
|
||||
source: anyhow::anyhow!("Invalid file format"),
|
||||
});
|
||||
}
|
||||
if &buf[0..4] == b"SSTM" || &buf[16..20] == b"STDM" || &buf[0..4] == b"RSTM" {
|
||||
return get_radar_data(buf);
|
||||
} else {
|
||||
return Err(ETWSError::FormatError {
|
||||
source: anyhow::anyhow!("Invalid file format"),
|
||||
});
|
||||
}
|
||||
} else {
|
||||
let mut file = File::open(path).unwrap();
|
||||
let mut file = File::open(path)?;
|
||||
let mut buf = Vec::new();
|
||||
file.read_to_end(&mut buf).unwrap();
|
||||
file.read_to_end(&mut buf)?;
|
||||
if buf.len() < 4 {
|
||||
return Err(ETWSError::FormatError {
|
||||
source: anyhow::anyhow!("Invalid file format"),
|
||||
});
|
||||
}
|
||||
if &buf[0..4] == b"SSTM" || &buf[16..20] == b"STDM" || &buf[0..4] == b"RSTM" {
|
||||
return get_radar_data(buf);
|
||||
} else {
|
||||
panic!("Invalid file format");
|
||||
return Err(ETWSError::FormatError {
|
||||
source: anyhow::anyhow!("Invalid file format"),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_radar_data(data: Vec<u8>) -> io::Result<RadarData> {
|
||||
fn get_radar_data(data: Vec<u8>) -> Result<RadarData, ETWSError> {
|
||||
let total_length = data.len() as u64;
|
||||
// 使用 Cursor 来处理 Vec<u8>
|
||||
let mut cursor = Cursor::new(data);
|
||||
@ -279,24 +330,24 @@ fn get_radar_data(data: Vec<u8>) -> io::Result<RadarData> {
|
||||
// 读取 GENERIC_HEADER
|
||||
let mut buffer = vec![0u8; 32];
|
||||
cursor.read_exact(&mut buffer)?;
|
||||
let (_, generic_header) = parse_generic_header(&buffer).unwrap();
|
||||
let (_, generic_header) = parse_generic_header(&buffer)?;
|
||||
|
||||
// 读取 SITE_CONFIG
|
||||
let mut buffer = vec![0u8; 128];
|
||||
cursor.read_exact(&mut buffer)?;
|
||||
let (_, site_config) = parse_site_config(&buffer).unwrap();
|
||||
let (_, site_config) = parse_site_config(&buffer)?;
|
||||
|
||||
// 读取 TASK_CONFIG
|
||||
let mut buffer = vec![0u8; 256];
|
||||
cursor.read_exact(&mut buffer)?;
|
||||
let (_, task_config) = parse_task_config(&buffer).unwrap();
|
||||
let (_, task_config) = parse_task_config(&buffer)?;
|
||||
|
||||
// 读取 SCAN_CONFIG
|
||||
let mut scan_configs = Vec::new();
|
||||
for _ in 0..task_config.scan_beam_number {
|
||||
let mut buffer = vec![0u8; 640];
|
||||
cursor.read_exact(&mut buffer)?;
|
||||
let (_, scan_config) = parse_scan_config(&buffer).unwrap();
|
||||
let (_, scan_config) = parse_scan_config(&buffer)?;
|
||||
scan_configs.push(scan_config);
|
||||
}
|
||||
|
||||
@ -305,7 +356,7 @@ fn get_radar_data(data: Vec<u8>) -> io::Result<RadarData> {
|
||||
for _ in 0..task_config.cut_number {
|
||||
let mut buffer = vec![0u8; 256];
|
||||
cursor.read_exact(&mut buffer)?;
|
||||
let (_, beam_config) = parse_beam_config(&buffer).unwrap();
|
||||
let (_, beam_config) = parse_beam_config(&buffer)?;
|
||||
beam_configs.push(beam_config);
|
||||
}
|
||||
|
||||
@ -454,19 +505,22 @@ fn parse_final_data(
|
||||
all_length: u64,
|
||||
cut_number: usize,
|
||||
mut cursor: Cursor<Vec<u8>>,
|
||||
) -> io::Result<(
|
||||
HashMap<&'static str, Vec<f64>>,
|
||||
Vec<f64>,
|
||||
Vec<f64>,
|
||||
Vec<f64>,
|
||||
)> {
|
||||
) -> Result<
|
||||
(
|
||||
HashMap<&'static str, Vec<f64>>,
|
||||
Vec<f64>,
|
||||
Vec<f64>,
|
||||
Vec<f64>,
|
||||
),
|
||||
ETWSError,
|
||||
> {
|
||||
let position = cursor.position();
|
||||
let mut radial_buffer = vec![0u8; 128];
|
||||
let mut header_buffer = vec![0u8; 32];
|
||||
cursor.read_exact(&mut radial_buffer)?;
|
||||
|
||||
// First Block
|
||||
let (_, radial_data) = parse_radial_data(&radial_buffer).unwrap();
|
||||
let (_, radial_data) = parse_radial_data(&radial_buffer)?;
|
||||
// Radial_number: I don't know why not use it.
|
||||
// let radial_number = radial_data.radial_number as usize;
|
||||
|
||||
@ -480,7 +534,7 @@ fn parse_final_data(
|
||||
|
||||
for idx in 0..type_number {
|
||||
cursor.read_exact(&mut header_buffer)?;
|
||||
let (_, header) = parse_type_header(&header_buffer).unwrap();
|
||||
let (_, header) = parse_type_header(&header_buffer)?;
|
||||
let first_beam_block = beam_block_exact(&mut cursor, &header)?;
|
||||
let first_beam = single_beam_block(&first_beam_block, header.bin_length as usize)?;
|
||||
gate_len[idx] = first_beam.len();
|
||||
@ -516,31 +570,32 @@ fn parse_final_data(
|
||||
for e in 0..cut_number {
|
||||
for a in 0..azm_number {
|
||||
cursor.read_exact(&mut radial_buffer)?;
|
||||
let (_, radial_data) = parse_radial_data(&radial_buffer).unwrap();
|
||||
let (_, radial_data) = parse_radial_data(&radial_buffer)?;
|
||||
els[e] = radial_data.elevation as f64;
|
||||
azs[a] = radial_data.azimuth as f64;
|
||||
let type_number = radial_data.moment_number as usize;
|
||||
for typ in 0..type_number {
|
||||
cursor.read_exact(&mut header_buffer)?;
|
||||
let (_, header) = parse_type_header(&header_buffer).unwrap();
|
||||
let (_, header) = parse_type_header(&header_buffer)?;
|
||||
let beam_block = beam_block_exact(&mut cursor, &header)?;
|
||||
let mut beam = single_beam_block(&beam_block, header.bin_length as usize)?;
|
||||
|
||||
beam.iter_mut()
|
||||
.for_each(|v| *v = (*v - header.offset as f64) / header.scale as f64);
|
||||
|
||||
let typ_name = types.get(typ).unwrap();
|
||||
if let Some(typ_name) = types.get(typ) {
|
||||
if typ_name == &"Unknown" {
|
||||
continue;
|
||||
}
|
||||
let e = radial_data.elevation_number as usize - 1;
|
||||
|
||||
if typ_name == &"Unknown" {
|
||||
datas.get_mut(typ_name).unwrap()[e * (azm_number * gate_len[typ])
|
||||
+ a * gate_len[typ]
|
||||
..e * (azm_number * gate_len[typ]) + (a + 1) * gate_len[typ]]
|
||||
.copy_from_slice(&beam);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
let e = radial_data.elevation_number as usize - 1;
|
||||
|
||||
datas.get_mut(typ_name).unwrap()[e * (azm_number * gate_len[typ])
|
||||
+ a * gate_len[typ]
|
||||
..e * (azm_number * gate_len[typ]) + (a + 1) * gate_len[typ]]
|
||||
.copy_from_slice(&beam);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -7,12 +7,13 @@ use super::{
|
||||
sidebar::{SideBarInputMsg, SideBarModel},
|
||||
ControlPanelOutputMsg, TimelineMsg,
|
||||
};
|
||||
use crate::datapool::{DataPool, Value};
|
||||
use crate::predefined::color_mapper::{BoundaryNorm, ColorMapper, ColorMapperComb, Discrete};
|
||||
use crate::widgets::{DynamicCol, ElementType};
|
||||
use crate::{plugin_system::init_plugin, widgets::render::Layer, PLUGIN_MANAGER};
|
||||
use crate::{widgets::render::Layer, PLUGIN_MANAGER};
|
||||
use chrono::{prelude::*, Duration};
|
||||
use gtk::Widget;
|
||||
use once_cell::sync::Lazy;
|
||||
use radarg_core::datapool::{DataPool, Value};
|
||||
use radarg_core::Data;
|
||||
use relm4::{
|
||||
actions::{AccelsPlus, RelmAction, RelmActionGroup},
|
||||
@ -61,15 +62,16 @@ pub enum FileIOType {
|
||||
pub enum AppMsg {
|
||||
Refresh,
|
||||
FileIO { typ: FileIOType },
|
||||
OpenDialog,
|
||||
OpenDialog { widget: Widget },
|
||||
CloseDialog,
|
||||
OpenAlert { body: String, title: String },
|
||||
CloseAlert,
|
||||
CloseRequest,
|
||||
Close,
|
||||
OpenFileDialog,
|
||||
}
|
||||
#[tracker::track]
|
||||
pub struct AppModel {
|
||||
waiting_for: Option<DateTime<Utc>>,
|
||||
|
||||
// Components
|
||||
#[do_not_track]
|
||||
open_dialog: Controller<OpenDialog>,
|
||||
@ -81,12 +83,6 @@ pub struct AppModel {
|
||||
sidebar: Controller<SideBarModel>,
|
||||
#[do_not_track]
|
||||
setting: Controller<SettingModel>,
|
||||
|
||||
// Data
|
||||
selected_layer: Vec<usize>,
|
||||
#[do_not_track]
|
||||
layers: Share<Vec<Layer>>,
|
||||
|
||||
// File Pool
|
||||
#[do_not_track]
|
||||
file_pool: Share<DataPool>,
|
||||
@ -184,16 +180,10 @@ impl Component for AppModel {
|
||||
set_title: "Dialog",
|
||||
set_presentation_mode: adw::DialogPresentationMode::Floating,
|
||||
set_follows_content_size: true,
|
||||
set_can_close: true,
|
||||
set_can_close: true
|
||||
},
|
||||
alert_dialog = adw::AlertDialog{
|
||||
|
||||
#[wrap(Some)]
|
||||
set_child=>k::Box{
|
||||
set_height_request: 200,
|
||||
set_width_request: 200,
|
||||
gtk::Label{
|
||||
set_text:"Dialog",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,21 +210,14 @@ impl Component for AppModel {
|
||||
root: Self::Root,
|
||||
sender: ComponentSender<Self>,
|
||||
) -> ComponentParts<Self> {
|
||||
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 data_pool = DataPool::new(10);
|
||||
let data_pool = DataPool::new(&PLUGIN_MANAGER, 10);
|
||||
let data_pool = Rc::new(RefCell::new(data_pool));
|
||||
|
||||
// SideBar Component
|
||||
let sidebar = SideBarModel::builder()
|
||||
.launch(None)
|
||||
.forward(sender.input_sender(), |msg| match msg {
|
||||
SideBarOutputMsg::Dialog(widget) => AppMsg::OpenDialog { widget },
|
||||
SideBarOutputMsg::QueueDraw => AppMsg::Refresh,
|
||||
_ => AppMsg::Close,
|
||||
});
|
||||
@ -242,7 +225,7 @@ impl Component for AppModel {
|
||||
let sidebar_sender = sidebar.sender();
|
||||
|
||||
// Monitor Component
|
||||
let render = MonitorModel::builder().launch(layers.clone()).forward(
|
||||
let render = MonitorModel::builder().launch(()).forward(
|
||||
sender.input_sender(),
|
||||
clone!(
|
||||
#[strong]
|
||||
@ -250,11 +233,22 @@ impl Component for AppModel {
|
||||
move |model_message| match model_message {
|
||||
MonitorOutputMsg::Attached(new_module) => {
|
||||
sidebar_sender.emit(SideBarInputMsg::Package(new_module));
|
||||
AppMsg::OpenDialog
|
||||
// AppMsg::Close
|
||||
AppMsg::CloseDialog
|
||||
}
|
||||
MonitorOutputMsg::Dialog(widget) => {
|
||||
AppMsg::OpenDialog { widget }
|
||||
}
|
||||
MonitorOutputMsg::DialogClose => {
|
||||
AppMsg::CloseDialog
|
||||
}
|
||||
MonitorOutputMsg::Alert(content, title) => {
|
||||
AppMsg::OpenAlert {
|
||||
body: content,
|
||||
title,
|
||||
}
|
||||
}
|
||||
MonitorOutputMsg::Fc => {
|
||||
AppMsg::OpenDialog
|
||||
AppMsg::Close
|
||||
}
|
||||
_ => AppMsg::Close,
|
||||
}
|
||||
@ -287,7 +281,10 @@ impl Component for AppModel {
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Failed to load data, cause: {:?}", e);
|
||||
AppMsg::Close
|
||||
AppMsg::OpenAlert {
|
||||
body: format!("Failed to load data, cause: {:?}", e),
|
||||
title: "Error".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -298,15 +295,12 @@ impl Component for AppModel {
|
||||
};
|
||||
|
||||
let model = AppModel {
|
||||
waiting_for: None,
|
||||
render,
|
||||
setting,
|
||||
open_dialog: dialog,
|
||||
selected_layer: vec![],
|
||||
sidebar,
|
||||
file_pool: data_pool,
|
||||
// control,
|
||||
layers,
|
||||
tracker: 0,
|
||||
};
|
||||
|
||||
@ -315,7 +309,6 @@ impl Component for AppModel {
|
||||
let widgets = view_output!();
|
||||
let mut group = RelmActionGroup::<FileActionGroup>::new();
|
||||
relm4::main_application().set_accelerators_for_action::<OpenAction>(&["<primary>O"]);
|
||||
// register_layer_actions(&widgets.main_window, sender.clone());
|
||||
let action: RelmAction<OpenAction> = {
|
||||
RelmAction::new_stateless(move |_| {
|
||||
sender.input(AppMsg::OpenFileDialog);
|
||||
@ -343,9 +336,24 @@ impl Component for AppModel {
|
||||
AppMsg::OpenFileDialog => {
|
||||
self.open_dialog.emit(OpenDialogMsg::Open);
|
||||
}
|
||||
AppMsg::OpenDialog => {
|
||||
AppMsg::OpenDialog { widget } => {
|
||||
widgets.dialog.set_child(Some(&widget));
|
||||
widgets.dialog.present(Some(root));
|
||||
}
|
||||
AppMsg::CloseDialog => {
|
||||
widgets.dialog.close();
|
||||
}
|
||||
AppMsg::OpenAlert { body, title } => {
|
||||
widgets.alert_dialog.set_body(&body);
|
||||
widgets.alert_dialog.set_title(&title);
|
||||
widgets.alert_dialog.add_responses(&[("Close", "Close")]);
|
||||
|
||||
widgets
|
||||
.alert_dialog
|
||||
.set_response_appearance("Close", adw::ResponseAppearance::Destructive);
|
||||
|
||||
widgets.alert_dialog.present(Some(root));
|
||||
}
|
||||
AppMsg::FileIO {
|
||||
typ: FileIOType::Open(data),
|
||||
} => self.render.emit(MonitorInputMsg::PushData(data)),
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
use super::messages::*;
|
||||
use super::thumbnail::{ImgItem, TypedListView};
|
||||
use crate::plugin_system::init_plugin;
|
||||
use crate::predefined::color_mapper::BoundaryNorm;
|
||||
use crate::widgets::render::Layer;
|
||||
use crate::widgets::timeline::{Selection, TimeLine};
|
||||
|
||||
136
radar-g/src/components/monitor/dialog_widget.rs
Normal file
136
radar-g/src/components/monitor/dialog_widget.rs
Normal file
@ -0,0 +1,136 @@
|
||||
use epoxy::S;
|
||||
use gi::pg::ModuleRefs;
|
||||
use gtk::Widget;
|
||||
use radarg_core::Data;
|
||||
use std::collections::HashMap;
|
||||
|
||||
use relm4::{
|
||||
adw::{self, prelude::*},
|
||||
factory::FactoryVecDeque,
|
||||
gtk::{self, prelude::*},
|
||||
prelude::*,
|
||||
view, ComponentParts, ComponentSender, SimpleComponent,
|
||||
};
|
||||
|
||||
use crate::widgets;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ItemInfo {
|
||||
pub module_name: &'static str,
|
||||
pub module_icon: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DialogOutput {
|
||||
Cancel,
|
||||
Open(usize),
|
||||
}
|
||||
pub struct Dialog {}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
impl SimpleComponent for Dialog {
|
||||
type Widgets = DialogWidgets;
|
||||
type Init = HashMap<(usize, String), Vec<ItemInfo>>;
|
||||
type Input = ();
|
||||
type Output = DialogOutput;
|
||||
|
||||
view! {
|
||||
root=adw::BreakpointBin {
|
||||
set_height_request:600,
|
||||
set_width_request:800,
|
||||
|
||||
#[wrap(Some)]
|
||||
set_child=&adw::ToolbarView{
|
||||
set_hexpand:true,
|
||||
set_vexpand:true,
|
||||
add_top_bar=&adw::HeaderBar{
|
||||
set_hexpand:true,
|
||||
#[wrap(Some)]
|
||||
set_title_widget=>k::Label{
|
||||
set_label: "Header",
|
||||
},
|
||||
},
|
||||
#[wrap(Some)]
|
||||
set_content=&adw::Clamp{
|
||||
set_hexpand:true,
|
||||
#[wrap(Some)]
|
||||
#[name(content)]
|
||||
set_child=>k::Box{
|
||||
set_orientation: gtk::Orientation::Vertical,
|
||||
set_hexpand:true,
|
||||
set_spacing: 10,
|
||||
|
||||
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn init(
|
||||
init: Self::Init,
|
||||
root: Self::Root,
|
||||
sender: relm4::ComponentSender<Self>,
|
||||
) -> relm4::ComponentParts<Self> {
|
||||
let widgets = view_output!();
|
||||
|
||||
if init.len() > 1 {
|
||||
view! {
|
||||
label=gtk::Label {
|
||||
set_label: "The file you opened contains multiple data blocks; please select one to proceed to the next step.",
|
||||
add_css_class: "h3",
|
||||
}
|
||||
}
|
||||
|
||||
widgets.content.append(&label);
|
||||
}
|
||||
|
||||
for ((k, name), v) in init.iter() {
|
||||
view! {
|
||||
tile=gtk::Expander{
|
||||
set_label: Some(&format!("Data {}: {}", k, name)),
|
||||
set_expanded: true,
|
||||
set_hexpand: true,
|
||||
#[name(content)]
|
||||
#[wrap(Some)]
|
||||
set_child=>k::FlowBox{
|
||||
set_homogeneous: true,
|
||||
set_column_spacing: 10,
|
||||
set_row_spacing: 10,
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
let data_id = *k;
|
||||
|
||||
for values in v.iter() {
|
||||
view! {
|
||||
item=gtk::Button {
|
||||
set_icon_name: &values.module_icon,
|
||||
connect_clicked[sender] => move |_| {
|
||||
sender.output(DialogOutput::Open(data_id));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
content.append(&item);
|
||||
}
|
||||
|
||||
widgets.content.append(&tile);
|
||||
}
|
||||
|
||||
let model = Self {};
|
||||
|
||||
// let widgets = model.sequence.widget().clone();
|
||||
// let contour = model.counter.widget().clone();
|
||||
|
||||
ComponentParts {
|
||||
model: model,
|
||||
widgets,
|
||||
}
|
||||
}
|
||||
|
||||
fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {}
|
||||
}
|
||||
@ -1,10 +1,12 @@
|
||||
use crate::datapool::Value;
|
||||
use gi::pg::ModulePackage;
|
||||
use gi::pg::{ModulePackage, Modules};
|
||||
use gtk::Widget;
|
||||
use radarg_core::datapool::Value;
|
||||
use radarg_core::Data;
|
||||
use std::{cell::RefCell, fmt::Debug, rc::Rc};
|
||||
use std::{cell::RefCell, fmt::Debug, rc::Rc, sync::Arc};
|
||||
|
||||
pub enum MonitorInputMsg {
|
||||
PushData(Value<Data>),
|
||||
Draw(Arc<Data>),
|
||||
QueueDraw,
|
||||
None,
|
||||
}
|
||||
@ -13,6 +15,9 @@ impl Debug for MonitorInputMsg {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
MonitorInputMsg::QueueDraw => write!(f, "MonitorInputMsg::QueueDraw"),
|
||||
MonitorInputMsg::Draw(data) => {
|
||||
write!(f, "MonitorInputMsg::Draw({:?})", data)
|
||||
}
|
||||
MonitorInputMsg::PushData(data) => write!(f, "MonitorInputMsg::PushData({:?})", data),
|
||||
MonitorInputMsg::None => write!(f, "MonitorInputMsg::None"),
|
||||
}
|
||||
@ -22,6 +27,9 @@ impl Debug for MonitorInputMsg {
|
||||
#[derive(Debug)]
|
||||
pub enum MonitorOutputMsg {
|
||||
Attached(Rc<RefCell<ModulePackage>>),
|
||||
Dialog(Widget),
|
||||
DialogClose,
|
||||
Alert(String, String),
|
||||
Fc,
|
||||
}
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
mod dialog_widget;
|
||||
pub mod messages;
|
||||
pub mod monitor;
|
||||
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
use super::dialog_widget::{Dialog, DialogOutput, ItemInfo};
|
||||
use super::messages::{MonitorInputMsg, MonitorOutputMsg};
|
||||
use crate::predefined::color_mapper::BoundaryNorm;
|
||||
use crate::widgets::render::RenderConfig;
|
||||
@ -8,9 +9,10 @@ use crate::{
|
||||
};
|
||||
use geo::k_nearest_concave_hull;
|
||||
use gi::graphics::transforms::plane::PlaneTrans;
|
||||
use gi::pg::ModulePackage;
|
||||
use gi::pg::{Module, ModulePackage};
|
||||
use gi::ui::operation::Operation;
|
||||
use gtk::glib::clone;
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
@ -21,6 +23,7 @@ use adw::prelude::*;
|
||||
use femtovg::ImageId;
|
||||
use fns::debounce;
|
||||
use gi::ui::typ::MainLoadAttach;
|
||||
use radarg_core::Data;
|
||||
use relm4::{component::Component, *};
|
||||
use slippy_map_tiles::Tile;
|
||||
use tokio::task;
|
||||
@ -49,7 +52,7 @@ pub struct MonitorWidgets {
|
||||
impl Component for MonitorModel {
|
||||
type CommandOutput = MonitorCommand;
|
||||
type Input = MonitorInputMsg;
|
||||
type Init = Rc<RefCell<Vec<Layer>>>;
|
||||
type Init = ();
|
||||
type Output = MonitorOutputMsg;
|
||||
|
||||
view! {
|
||||
@ -95,24 +98,60 @@ impl Component for MonitorModel {
|
||||
self.reset();
|
||||
match message {
|
||||
MonitorInputMsg::PushData(data) => {
|
||||
sender.output(MonitorOutputMsg::Fc);
|
||||
// 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);
|
||||
// }
|
||||
// })
|
||||
widgets.renderer.get_gi(|gi| {
|
||||
let supported_modules = gi.supported_modules(&data);
|
||||
|
||||
let mut result = HashMap::new();
|
||||
for (data, modules) in supported_modules {
|
||||
let mut module_packages = vec![];
|
||||
for module in modules {
|
||||
module_packages.push(ItemInfo {
|
||||
module_name: module.name(),
|
||||
module_icon: "plus",
|
||||
});
|
||||
}
|
||||
result.insert((data.id, data.description.clone()), module_packages);
|
||||
}
|
||||
|
||||
let dialog = Dialog::builder().launch(result).forward(
|
||||
sender.input_sender(),
|
||||
move |msg| match msg {
|
||||
DialogOutput::Open(index) => {
|
||||
let data = data.iter().find(|d| *d.0 == index).unwrap();
|
||||
MonitorInputMsg::Draw(data.1.clone())
|
||||
}
|
||||
_ => MonitorInputMsg::None,
|
||||
},
|
||||
);
|
||||
|
||||
let widget = dialog.widget().to_owned().upcast();
|
||||
|
||||
sender.output(MonitorOutputMsg::Dialog(widget));
|
||||
});
|
||||
}
|
||||
MonitorInputMsg::QueueDraw => {
|
||||
widgets.renderer.queue_draw();
|
||||
}
|
||||
MonitorInputMsg::Draw(ref data) => {
|
||||
widgets.renderer.get_gi(|gi| {
|
||||
let data: &Data = &*data;
|
||||
|
||||
match gi.program().ppi().load_data(data.into(), &SETTING) {
|
||||
Ok(package) => {
|
||||
let package = Rc::new(RefCell::new(package.into()));
|
||||
self.set_module_packages(vec![package.clone()]);
|
||||
sender.output(MonitorOutputMsg::Attached(package));
|
||||
}
|
||||
Err(e) => {
|
||||
error!("Error loading data: {:?}", e);
|
||||
sender.output(MonitorOutputMsg::Alert(e.to_string(), format!("Close")));
|
||||
}
|
||||
}
|
||||
|
||||
sender.input(MonitorInputMsg::QueueDraw);
|
||||
});
|
||||
sender.output(MonitorOutputMsg::DialogClose);
|
||||
}
|
||||
MonitorInputMsg::None => {}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@ -4,12 +4,13 @@ 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 gtk::{glib, Widget};
|
||||
use relm4::actions::{AccelsPlus, RelmAction};
|
||||
use relm4::RelmRemoveAllExt;
|
||||
use relm4::{
|
||||
adw::{self, prelude::*},
|
||||
binding::{Binding, U8Binding},
|
||||
factory::{DynamicIndex, FactoryComponent, FactorySender, FactoryVecDeque},
|
||||
gtk::gio,
|
||||
@ -18,7 +19,7 @@ use relm4::{
|
||||
column::TypedColumnView,
|
||||
list::{RelmListItem, TypedListView},
|
||||
},
|
||||
RelmObjectExt,
|
||||
view, RelmObjectExt,
|
||||
};
|
||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||
|
||||
@ -36,6 +37,7 @@ pub struct SideBarModel {
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SideBarOutputMsg {
|
||||
Dialog(Widget),
|
||||
QueueDraw,
|
||||
}
|
||||
|
||||
@ -54,7 +56,46 @@ impl Component for SideBarModel {
|
||||
set_margin_all: 5,
|
||||
|
||||
#[name="container"]
|
||||
gtk::Box {}
|
||||
gtk::Box {
|
||||
gtk::Button {
|
||||
set_hexpand:true,
|
||||
set_label: "Refresh",
|
||||
connect_clicked[sender] => move |_| {
|
||||
|
||||
view! {
|
||||
widget=adw::BreakpointBin{
|
||||
set_width_request: 800,
|
||||
set_height_request:600,
|
||||
|
||||
#[wrap(Some)]
|
||||
set_child=&adw::ToolbarView{
|
||||
set_hexpand:true,
|
||||
set_vexpand:true,
|
||||
|
||||
add_top_bar=&adw::HeaderBar{
|
||||
#[wrap(Some)]
|
||||
set_title_widget=>k::Label{
|
||||
set_label: "Header",
|
||||
},
|
||||
},
|
||||
|
||||
#[wrap(Some)]
|
||||
set_content=>k::Box{
|
||||
gtk::Button{
|
||||
set_label:"Expanders",
|
||||
},
|
||||
gtk::Button{
|
||||
set_label:"Expanders",
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
sender.output(SideBarOutputMsg::Dialog(widget.upcast()));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
|
||||
@ -1,54 +0,0 @@
|
||||
use crate::PLUGIN_MANAGER;
|
||||
use quick_cache::sync::Cache;
|
||||
use radarg_core::errors::DataError;
|
||||
use radarg_core::Data;
|
||||
use std::fmt::Display;
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Value<T: Display>(Arc<Vec<T>>);
|
||||
|
||||
impl<T: Display> Value<T> {
|
||||
pub fn new(data: Vec<T>) -> Self {
|
||||
Self(Arc::new(data))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Display> Deref for Value<T> {
|
||||
type Target = Vec<T>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Value<Data> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for data in self.0.iter() {
|
||||
writeln!(f, "{}", data)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DataPool {
|
||||
pool: Cache<PathBuf, Value<Data>>,
|
||||
}
|
||||
|
||||
impl DataPool {
|
||||
pub fn new(cap: usize) -> Self {
|
||||
Self {
|
||||
pool: Cache::new(cap),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_or_load(&self, path: impl Into<PathBuf>) -> Result<Value<Data>, DataError> {
|
||||
let path = path.into();
|
||||
self.pool.get_or_insert_with(&path, || {
|
||||
PLUGIN_MANAGER.try_load_data(&path).map(Value::new)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -3,15 +3,13 @@
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
use gtk::{gio, prelude::SettingsExt};
|
||||
use plugin_system::{init_plugin, PluginManager};
|
||||
use radarg_core::plugin_system::{init_plugin, PluginManager};
|
||||
use std::convert::TryInto;
|
||||
use std::sync::RwLock;
|
||||
use std::{ptr, sync::Mutex};
|
||||
use tokio::runtime::Runtime;
|
||||
mod actions;
|
||||
mod components;
|
||||
mod datapool;
|
||||
mod plugin_system;
|
||||
use crate::components::app::AppMsg;
|
||||
use components::app::AppModel;
|
||||
use gi::{App as GI, Helper, GL};
|
||||
|
||||
@ -183,6 +183,8 @@ impl GLAreaImpl for Render {
|
||||
|
||||
viewport.unbind();
|
||||
|
||||
self.io.borrow_mut().reset();
|
||||
|
||||
glib::Propagation::Proceed
|
||||
}
|
||||
}
|
||||
|
||||
@ -63,9 +63,12 @@ impl Render {
|
||||
this,
|
||||
move |_, x, y| {
|
||||
this.imp().set_io(|io| {
|
||||
io.mouse.wheel_delta = y as f32;
|
||||
io.mouse.wheel_delta = -y as f32;
|
||||
});
|
||||
this.queue_draw();
|
||||
|
||||
if y != 0.0 {
|
||||
this.queue_draw();
|
||||
}
|
||||
glib::Propagation::Proceed
|
||||
}
|
||||
));
|
||||
@ -136,7 +139,7 @@ impl Render {
|
||||
f(&mut cfg);
|
||||
}
|
||||
|
||||
pub fn get_gi<F: FnMut(&mut GI)>(&self, mut f: F) {
|
||||
pub fn get_gi<F: FnOnce(&mut GI)>(&self, mut f: F) {
|
||||
let mut gi = self.imp().gi.borrow_mut();
|
||||
f(&mut gi.as_mut().unwrap());
|
||||
}
|
||||
|
||||
@ -15,6 +15,9 @@ dirs = "5.0.1"
|
||||
num-traits = "0.2.19"
|
||||
serde = { version = "1.0.209", features = ["derive"] }
|
||||
relm4 = { version = "0.9.0", features = ["libadwaita"] }
|
||||
abi_stable = "0.11.3"
|
||||
core_extensions = "1.5.3"
|
||||
quick_cache = "0.6.5"
|
||||
|
||||
[dependencies.radarg_plugin_interface]
|
||||
version = "0.1"
|
||||
|
||||
76
radarg_core/src/datapool/mod.rs
Normal file
76
radarg_core/src/datapool/mod.rs
Normal file
@ -0,0 +1,76 @@
|
||||
use crate::errors::DataError;
|
||||
use crate::plugin_system::PluginManager;
|
||||
use crate::Data;
|
||||
use quick_cache::sync::Cache;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::Display;
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct Value<T: Display>(Arc<HashMap<usize, Arc<T>>>);
|
||||
|
||||
impl Value<Data> {
|
||||
pub fn new(data: Vec<Data>) -> Self {
|
||||
let mut hashmap = HashMap::new();
|
||||
for data in data {
|
||||
hashmap.insert(data.id, Arc::new(data));
|
||||
}
|
||||
|
||||
Self(Arc::new(hashmap))
|
||||
}
|
||||
|
||||
pub fn get(&self, key: usize) -> Option<&Arc<Data>> {
|
||||
self.0.get(&key)
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> std::collections::hash_map::Iter<'_, usize, Arc<Data>> {
|
||||
self.0.iter()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Display> Value<T> {
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.len()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Display> Deref for Value<T> {
|
||||
type Target = HashMap<usize, Arc<T>>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Value<Data> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for data in self.0.iter() {
|
||||
writeln!(f, "{:?}", data)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DataPool {
|
||||
plugin_manager: &'static PluginManager,
|
||||
pool: Cache<PathBuf, Value<Data>>,
|
||||
}
|
||||
|
||||
impl DataPool {
|
||||
pub fn new(plugin_manager: &'static PluginManager, cap: usize) -> Self {
|
||||
Self {
|
||||
plugin_manager,
|
||||
pool: Cache::new(cap),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_or_load(&self, path: impl Into<PathBuf>) -> Result<Value<Data>, DataError> {
|
||||
let path = path.into();
|
||||
self.pool.get_or_insert_with(&path, || {
|
||||
self.plugin_manager.try_load_data(&path).map(Value::new)
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -2,6 +2,8 @@ pub mod config;
|
||||
pub mod errors;
|
||||
pub mod radarg_data;
|
||||
use rust_embed::RustEmbed;
|
||||
pub mod datapool;
|
||||
pub mod plugin_system;
|
||||
pub mod utils;
|
||||
pub mod widget_interface;
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
use crate::errors::DataError;
|
||||
use crate::Data;
|
||||
use abi_stable::{
|
||||
external_types::crossbeam_channel::{self, RReceiver, RSender},
|
||||
library::{lib_header_from_path, LibraryError, LibrarySuffix, RawLibrary},
|
||||
@ -5,8 +7,6 @@ use abi_stable::{
|
||||
std_types::{RBox, RErr, ROk, RResult, RSome, RStr, RString, RVec},
|
||||
};
|
||||
use core_extensions::*;
|
||||
use radarg_core::errors::DataError;
|
||||
use radarg_core::Data;
|
||||
use radarg_plugin_interface::{DataLoaderPlugin, DataLoaderPlugin_TO, PluginId, PluginMod_Ref};
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
@ -1,25 +1,61 @@
|
||||
use std::{fmt::Display, rc::Rc};
|
||||
use std::{
|
||||
fmt::Display,
|
||||
hash::Hash,
|
||||
rc::Rc,
|
||||
sync::{atomic::AtomicUsize, Arc},
|
||||
};
|
||||
|
||||
use chrono::Utc;
|
||||
use ndarray::ArrayD;
|
||||
use radarg_plugin_interface::{
|
||||
LoadedData, ProbeDataType as RPT, RadarGridData as RawRadarGridData, VecResult::*,
|
||||
DataLoaderPlugin, LoadedData, ProbeDataType as RPT, RadarGridData as RawRadarGridData,
|
||||
VecResult::*,
|
||||
};
|
||||
|
||||
static DATA_ID: AtomicUsize = AtomicUsize::new(0);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum Data {
|
||||
RadarGridData(Rc<RadarGridData>),
|
||||
pub struct Data {
|
||||
pub id: usize,
|
||||
pub description: String,
|
||||
_data: _Data,
|
||||
}
|
||||
|
||||
impl PartialEq for Data {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.id == other.id
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for Data {
|
||||
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||
self.id.hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for Data {}
|
||||
|
||||
impl Display for Data {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self._data)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum _Data {
|
||||
RadarGridData(Arc<RadarGridData>),
|
||||
JsonData,
|
||||
PlainText(String),
|
||||
Binary(Vec<u8>),
|
||||
}
|
||||
|
||||
impl Display for Data {
|
||||
impl Display for _Data {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Data::RadarGridData(info) => write!(f, "RadarGridData: {}", info),
|
||||
Data::JsonData => write!(f, "JsonData"),
|
||||
Data::PlainText(_) => write!(f, "PlainText"),
|
||||
Data::Binary(_) => write!(f, "Binary"),
|
||||
_Data::RadarGridData(info) => write!(f, "RadarGridData: {}", info),
|
||||
_Data::JsonData => write!(f, "JsonData"),
|
||||
_Data::PlainText(_) => write!(f, "PlainText"),
|
||||
_Data::Binary(_) => write!(f, "Binary"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -113,7 +149,7 @@ impl Display for RadarGridData {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct GridDataInfo {
|
||||
pub shape: Vec<usize>,
|
||||
pub dimensions: Vec<Vec<f64>>,
|
||||
@ -228,13 +264,62 @@ raw2new!(
|
||||
)
|
||||
);
|
||||
|
||||
impl From<LoadedData> for Data {
|
||||
impl From<LoadedData> for _Data {
|
||||
fn from(value: LoadedData) -> Self {
|
||||
match value {
|
||||
LoadedData::Binary(v) => Data::Binary(v.into_vec()),
|
||||
LoadedData::JsonData => Data::JsonData,
|
||||
LoadedData::PlainText(v) => Data::PlainText(v.into_string()),
|
||||
LoadedData::RadarGridData(v) => Data::RadarGridData(Rc::new(v.into())),
|
||||
LoadedData::Binary(v) => _Data::Binary(v.into_vec()),
|
||||
LoadedData::JsonData => _Data::JsonData,
|
||||
LoadedData::PlainText(v) => _Data::PlainText(v.into_string()),
|
||||
LoadedData::RadarGridData(v) => _Data::RadarGridData(Arc::new(v.into())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<LoadedData> for Data {
|
||||
fn from(value: LoadedData) -> Self {
|
||||
let description = match &value {
|
||||
LoadedData::Binary(_) => "Binary".into(),
|
||||
LoadedData::JsonData => "JsonData".into(),
|
||||
LoadedData::PlainText(_) => "PlainText".into(),
|
||||
LoadedData::RadarGridData(v) => format!("{}", v.info.value_name),
|
||||
};
|
||||
Data {
|
||||
id: DATA_ID.fetch_add(1, std::sync::atomic::Ordering::SeqCst),
|
||||
description: description,
|
||||
_data: value.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl<'a> From<&'a Data> for &'a Rc<RadarGridData> {
|
||||
// fn from(data: &'a Data) -> Self {
|
||||
// match &data._data {
|
||||
// _Data::RadarGridData(v) => v,
|
||||
// _ => panic!("Unsupported data type"),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
impl<'a> From<&'a Data> for &'a Arc<RadarGridData> {
|
||||
fn from(data: &'a Data) -> Self {
|
||||
match &data._data {
|
||||
_Data::RadarGridData(v) => v,
|
||||
_ => panic!("Unsupported data type"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod test {
|
||||
use std::rc::Rc;
|
||||
|
||||
use super::RadarGridData;
|
||||
|
||||
use super::Data;
|
||||
|
||||
fn test() {
|
||||
let radar_data = RadarGridData {
|
||||
data: ndarray::ArrayD::from_shape_vec(ndarray::IxDyn(&[1, 1]), vec![1.0]).unwrap(),
|
||||
info: super::GridDataInfo::default(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user