rebuild factor
This commit is contained in:
parent
cd1d7023ed
commit
ed9e8549aa
121
Cargo.lock
generated
121
Cargo.lock
generated
@ -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"
|
||||
|
||||
@ -6,5 +6,5 @@ members = [
|
||||
"geo-macros",
|
||||
"radar-g",
|
||||
"gi",
|
||||
"radarg_data",
|
||||
"radarg_core",
|
||||
]
|
||||
|
||||
217
config.toml
Normal file
217
config.toml
Normal file
@ -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,
|
||||
]
|
||||
@ -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"
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -28,14 +28,18 @@ impl LinearColormap {
|
||||
}
|
||||
|
||||
pub fn set_unvalid_value(&mut self, value: f32) {
|
||||
if value != self.unvalid {
|
||||
self.unvalid = value;
|
||||
self.color_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_colors(&mut self, colors: Vec<[u8; 4]>) {
|
||||
if colors != self.colors {
|
||||
self.colors = colors;
|
||||
self.color_changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_range(&mut self, min: f32, max: f32) {
|
||||
self.min = min;
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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]);
|
||||
|
||||
@ -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 } => {
|
||||
|
||||
@ -6,7 +6,6 @@ mod errors;
|
||||
mod font_manager;
|
||||
pub mod graphics;
|
||||
pub mod pg;
|
||||
mod setting;
|
||||
mod shaders;
|
||||
pub mod ui;
|
||||
mod utils;
|
||||
|
||||
@ -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<Data>) -> Result<ModulePackage> {
|
||||
self.program().load_data(data)
|
||||
pub fn load_data(
|
||||
&mut self,
|
||||
data: &Vec<Data>,
|
||||
setting: &radarg_core::config::Setting,
|
||||
) -> Result<ModulePackage> {
|
||||
self.program().load_data(data, setting)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
115
gi/src/pg/mod.rs
115
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<RefCell<ModulePackage>>),
|
||||
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<Data>) -> Result<ModulePackage> {
|
||||
pub fn load_data(
|
||||
&mut self,
|
||||
data: &Vec<Data>,
|
||||
setting: &radarg_core::config::Setting,
|
||||
) -> Result<ModulePackage> {
|
||||
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,29 +125,65 @@ macro_rules! impl_module_package {
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ModulePackage {
|
||||
pub enum ComponentBuilders {
|
||||
$(
|
||||
$b(ComponentBuilder<$c>, Rc<RefCell<<$t as ModuleCursor>::Config>>, Box<dyn Fn(<$t as ModuleCursor>::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,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum _ModulePackage {
|
||||
PPI(PPIPackage),
|
||||
}
|
||||
impl ModulePackage {
|
||||
|
||||
impl_module_package!({
|
||||
PPIPackage => PPI
|
||||
});
|
||||
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<T> From<T> for ModulePackage
|
||||
where
|
||||
}
|
||||
|
||||
impl ComponentBuilders {
|
||||
pub fn build<ROOT: IsA<Widget>>(self, package: &ModulePackage, root: &ROOT, sender: &Sender<SideBarInputMsg>) -> Components {
|
||||
match self {
|
||||
$(
|
||||
ComponentBuilders::$b(b, init, f) => Components::$b(b.launch(init).forward(sender, move |c| {f(c)})),
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl<T> From<T> 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),
|
||||
@ -125,14 +191,21 @@ where
|
||||
need_update: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for ModulePackage {
|
||||
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) {
|
||||
self.need_update = true;
|
||||
|
||||
@ -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<Self::Data>) -> Result<Self::Cursor>;
|
||||
fn load_data<'dt>(&self, data: &Rc<Self::Data>, setting: &Setting) -> Result<Self::Cursor>;
|
||||
}
|
||||
|
||||
pub trait ModuleCursor {
|
||||
type Module<'rf, 'gl: 'rf>: Module;
|
||||
type Data;
|
||||
type Config;
|
||||
type Component: RComponent;
|
||||
|
||||
type ComponentOutput;
|
||||
|
||||
fn set_config<F>(&mut self, f: F)
|
||||
where
|
||||
F: FnOnce(&mut Self::Config);
|
||||
|
||||
fn component_config(&self) -> Rc<RefCell<Self::Config>>;
|
||||
|
||||
fn component_sender(&self) -> Box<dyn Fn(Self::ComponentOutput) -> SideBarInputMsg>;
|
||||
}
|
||||
|
||||
@ -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<Self::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<Self::Data>) -> Result<Self::Cursor> {
|
||||
fn load_data<'dt>(&self, data: &Rc<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);
|
||||
@ -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<RefCell<PPIModuleConfig>>,
|
||||
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<RefCell<PPIModuleConfig>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum OutputMsg {
|
||||
Refresh,
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
impl SimpleComponent for PPIModuleConfigComponent {
|
||||
type Widgets = PPIModuleConfigComponentWidgets;
|
||||
type Init = Rc<RefCell<PPIModuleConfig>>;
|
||||
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<Self>,
|
||||
) -> relm4::ComponentParts<Self> {
|
||||
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<Self>) {}
|
||||
}
|
||||
|
||||
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<F>(&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<RefCell<Self::Config>> {
|
||||
self.ppi_config.clone()
|
||||
}
|
||||
|
||||
fn component_sender(&self) -> Box<dyn Fn(Self::ComponentOutput) -> crate::pg::SideBarInputMsg> {
|
||||
Box::new(|c| match c {
|
||||
OutputMsg::Refresh => SideBarInputMsg::Refresh,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
[plugins]
|
||||
etws_loader = { version = "0.1.0" }
|
||||
@ -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<OpenDialog>,
|
||||
#[do_not_track]
|
||||
control: Controller<ControlPanelModel>,
|
||||
// #[do_not_track]
|
||||
// control: Controller<ControlPanelModel>,
|
||||
#[do_not_track]
|
||||
render: Controller<MonitorModel>,
|
||||
#[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<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 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);
|
||||
|
||||
@ -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<Data>),
|
||||
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"),
|
||||
}
|
||||
|
||||
@ -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,7 +95,9 @@ impl Component for MonitorModel {
|
||||
self.reset();
|
||||
match message {
|
||||
MonitorInputMsg::PushData(data) => {
|
||||
widgets.renderer.get_gi(|gi| match gi.load_data(&data) {
|
||||
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));
|
||||
@ -106,6 +109,9 @@ impl Component for MonitorModel {
|
||||
}
|
||||
})
|
||||
}
|
||||
MonitorInputMsg::QueueDraw => {
|
||||
widgets.renderer.queue_draw();
|
||||
}
|
||||
MonitorInputMsg::None => {}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -2,3 +2,4 @@ pub mod sidebar;
|
||||
pub use sidebar::*;
|
||||
pub mod bottom_bar;
|
||||
pub mod meta_data_list;
|
||||
pub use gi::pg::SideBarInputMsg;
|
||||
|
||||
@ -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<RefCell<Vec<Layer>>>,
|
||||
selected_layer_idx: usize,
|
||||
counter: u8,
|
||||
list_view_wrapper: TypedListView<LayerItem, gtk::MultiSelection>,
|
||||
bottom_bar_vec: FactoryVecDeque<BottomBarModel>,
|
||||
meta_list_view: TypedColumnView<MyListItem, gtk::NoSelection>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SideBarInputMsg {
|
||||
AddMetaItems(HashMap<String, String>),
|
||||
ClearMetaItems,
|
||||
RefreshList,
|
||||
None,
|
||||
components: Option<Components>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SideBarOutputMsg {
|
||||
SelectLayer(Vec<usize>),
|
||||
NewLayer(Layer),
|
||||
SwitchToTimeSeries(usize),
|
||||
QueueDraw,
|
||||
}
|
||||
|
||||
#[relm4::component(pub)]
|
||||
impl SimpleComponent for SideBarModel {
|
||||
type Init = Rc<RefCell<Vec<Layer>>>;
|
||||
impl Component for SideBarModel {
|
||||
type Init = Option<Components>;
|
||||
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<Self>,
|
||||
) -> ComponentParts<Self> {
|
||||
// Initialize the ListView wrapper
|
||||
let mut list_view_wrapper: TypedListView<LayerItem, gtk::MultiSelection> =
|
||||
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::<TagColumn>();
|
||||
meta_list_view.append_column::<InfoColumn>();
|
||||
|
||||
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::<Vec<_>>();
|
||||
model.list_view_wrapper.extend_from_iter(list);
|
||||
}
|
||||
|
||||
ComponentParts { model, widgets }
|
||||
}
|
||||
|
||||
fn update(&mut self, message: Self::Input, sender: ComponentSender<Self>) {
|
||||
fn update_with_view(
|
||||
&mut self,
|
||||
widgets: &mut Self::Widgets,
|
||||
message: Self::Input,
|
||||
sender: ComponentSender<Self>,
|
||||
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::<Vec<_>>();
|
||||
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<Utc>),
|
||||
Instance,
|
||||
BindToOtherLayer(usize),
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
|
||||
struct LayerItem {
|
||||
key: u32,
|
||||
layer_name: String,
|
||||
visiable: bool,
|
||||
status: LayerStatus,
|
||||
img: Option<gtk::gdk::Texture>,
|
||||
}
|
||||
|
||||
impl LayerItem {
|
||||
fn new(
|
||||
key: u32,
|
||||
name: String,
|
||||
visiable: bool,
|
||||
img: Option<gtk::gdk::Texture>,
|
||||
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!("<b>Opacity:</b> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -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;
|
||||
|
||||
@ -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<Runtime> =
|
||||
SafeLazy::new(|| Runtime::new().expect("Setting up tokio runtime needs to succeed."));
|
||||
static PLUGIN_MANAGER: SafeLazy<PluginManager> = SafeLazy::new(|| PluginManager::new().unwrap());
|
||||
static SETTING: SafeLazy<radarg_core::config::Setting> =
|
||||
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 =
|
||||
|
||||
@ -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},
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<f64>,
|
||||
#[property(get, set)]
|
||||
scale: Cell<f64>,
|
||||
pub(super) io: RefCell<IO>,
|
||||
pub(super) opeartion: RefCell<Operation<PlaneTrans>>,
|
||||
pub(super) exterior: RefCell<ExteriorWidget>,
|
||||
pub(super) interior: RefCell<InteriorWidget>,
|
||||
@ -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<F: FnMut(&mut 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();
|
||||
|
||||
@ -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::{
|
||||
|
||||
@ -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();
|
||||
}
|
||||
));
|
||||
|
||||
|
||||
21
radarg_core/Cargo.toml
Normal file
21
radarg_core/Cargo.toml
Normal file
@ -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"
|
||||
@ -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<CB>,
|
||||
}
|
||||
|
||||
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<Vec<[u8; 4]>> {
|
||||
pub fn color(&self) -> Result<Vec<[u8; 4]>, 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::<std::result::Result<Vec<_>, 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);
|
||||
|
||||
@ -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,
|
||||
}
|
||||
12
radarg_core/src/lib.rs
Normal file
12
radarg_core/src/lib.rs
Normal file
@ -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::*;
|
||||
18
radarg_core/src/utils/color_tools.rs
Normal file
18
radarg_core/src/utils/color_tools.rs
Normal file
@ -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])
|
||||
}
|
||||
1
radarg_core/src/utils/mod.rs
Normal file
1
radarg_core/src/utils/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod color_tools;
|
||||
217
radarg_core/statics/config.toml
Normal file
217
radarg_core/statics/config.toml
Normal file
@ -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,
|
||||
]
|
||||
@ -1,14 +0,0 @@
|
||||
[package]
|
||||
name = "radarg_data"
|
||||
version = "0.1.0"
|
||||
authors = ["tsuki <tsuki@keitsuki.top>"]
|
||||
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"
|
||||
Loading…
Reference in New Issue
Block a user