diff --git a/.idea/.gitignore b/.idea/.gitignore deleted file mode 100644 index 13566b8..0000000 --- a/.idea/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -# Default ignored files -/shelf/ -/workspace.xml -# Editor-based HTTP Client requests -/httpRequests/ -# Datasource local storage ignored files -/dataSources/ -/dataSources.local.xml diff --git a/.idea/cinrad_g.iml b/.idea/cinrad_g.iml deleted file mode 100644 index cf84ae4..0000000 --- a/.idea/cinrad_g.iml +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml deleted file mode 100644 index 2d78b2c..0000000 --- a/.idea/modules.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 35eb1dd..0000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 19d2f45..f74d4c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -72,6 +72,15 @@ dependencies = [ "syn 2.0.29", ] +[[package]] +name = "atomic-polyfill" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ff7eb3f316534d83a8a2c3d1674ace8a5a71198eba31e2e2b597833f699b28" +dependencies = [ + "critical-section", +] + [[package]] name = "atty" version = "0.2.14" @@ -273,6 +282,7 @@ dependencies = [ "cairo-rs", "epoxy", "femtovg", + "geo", "geo-macros", "geo-types", "glib", @@ -293,6 +303,7 @@ dependencies = [ "quadtree_rs", "relm4", "relm4-components", + "rstar", "shapefile", "svg", "thiserror", @@ -373,6 +384,12 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7059fff8937831a9ae6f0fe4d658ffabf58f2ca96aa9dec1c889f936f705f216" + [[package]] name = "crossbeam-channel" version = "0.5.8" @@ -513,6 +530,16 @@ dependencies = [ "subtle", ] +[[package]] +name = "earcutr" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0812b44697951d35fde8fcb0da81c9de7e809e825a66bbf1ecb79d9829d4ca3d" +dependencies = [ + "itertools", + "num-traits", +] + [[package]] name = "either" version = "1.8.1" @@ -628,6 +655,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "float_next_after" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8" + [[package]] name = "flume" version = "0.10.14" @@ -821,6 +854,22 @@ dependencies = [ "version_check", ] +[[package]] +name = "geo" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1645cf1d7fea7dac1a66f7357f3df2677ada708b8d9db8e9b043878930095a96" +dependencies = [ + "earcutr", + "float_next_after", + "geo-types", + "geographiclib-rs", + "log", + "num-traits", + "robust", + "rstar", +] + [[package]] name = "geo-macros" version = "0.1.0" @@ -832,15 +881,25 @@ dependencies = [ [[package]] name = "geo-types" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1019f6d372c5b53143f08deee4168d05c22920fe5e0f51f0dfb0e8ffb67ec11e" +checksum = "9705398c5c7b26132e74513f4ee7c1d7dafd786004991b375c172be2be0eecaa" dependencies = [ "approx", "num-traits", + "rstar", "serde", ] +[[package]] +name = "geographiclib-rs" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea804e7bd3c6a4ca6a01edfa35231557a8a81d4d3f3e1e2b650d028c42592be" +dependencies = [ + "lazy_static", +] + [[package]] name = "getrandom" version = "0.2.10" @@ -1127,12 +1186,34 @@ dependencies = [ "crunchy", ] +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", +] + [[package]] name = "hashbrown" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a" +[[package]] +name = "heapless" +version = "0.7.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db04bc24a18b9ea980628ecf00e6c0264f3c1426dac36c00cb49b6fbad8b0743" +dependencies = [ + "atomic-polyfill", + "hash32", + "rustc_version", + "spin", + "stable_deref_trait", +] + [[package]] name = "heck" version = "0.4.1" @@ -1219,6 +1300,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "jobserver" version = "0.1.26" @@ -1997,6 +2087,23 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "robust" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf4a6aa5f6d6888f39e980649f3ad6b666acdce1d78e95b8a2cb076e687ae30" + +[[package]] +name = "rstar" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73111312eb7a2287d229f06c00ff35b51ddee180f017ab6dec1f69d62ac098d6" +dependencies = [ + "heapless", + "num-traits", + "smallvec", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -2169,6 +2276,12 @@ dependencies = [ "lock_api", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "strsim" version = "0.7.0" diff --git a/Cargo.toml b/Cargo.toml index 600215f..8af6241 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,6 +34,8 @@ anyhow = "1.0.72" proj5 = { version = "0.1.7", features = ["multithreading"] } relm4 = "0.6.1" relm4-components = "0.6.1" +rstar = "*" +geo = "0.26.0" diff --git a/ne_110m_admin_0_countries.zip b/ne_110m_admin_0_countries.zip new file mode 100644 index 0000000..aca6ab2 Binary files /dev/null and b/ne_110m_admin_0_countries.zip differ diff --git a/src/components/app.rs b/src/components/app.rs index 5bdb580..9c38660 100644 --- a/src/components/app.rs +++ b/src/components/app.rs @@ -2,6 +2,7 @@ use super::{control_panel::ControlPanelModel, render_panel::RenderPanelModel}; use gtk::{prelude::{ ApplicationExt, ButtonExt, DialogExt, GtkWindowExt, ToggleButtonExt, WidgetExt, }, traits::OrientableExt}; +use gtk::prelude::GtkApplicationExt; use relm4::*; #[derive(Debug)] @@ -23,6 +24,9 @@ pub struct AppModel { control: Controller, render: Controller, } +relm4::new_action_group!(WindowActionGroup, "win"); +relm4::new_stateless_action!(ExampleAction, WindowActionGroup, "example"); +relm4::new_stateful_action!(ExampleU8Action, WindowActionGroup, "example2", u8, u8); #[relm4::component(pub)] impl SimpleComponent for AppModel { @@ -31,12 +35,13 @@ impl SimpleComponent for AppModel { type Output = (); view! { - main_window = gtk::Window { - set_default_width: 1000, + main_window = gtk::ApplicationWindow { + set_default_width: 1200, set_default_height: 700, + set_focus_on_click:true, set_titlebar: Some(>k::HeaderBar::new()), gtk::Box{ - set_orientation: gtk::Orientation::Vertical, + set_orientation: gtk::Orientation::Horizontal, set_valign:gtk::Align::Fill, model.control.widget(), model.render.widget(), @@ -61,6 +66,42 @@ impl SimpleComponent for AppModel { .launch(0) .forward(sender.input_sender(), |a| AppMsg::Close); + relm4::menu! { + main_menu: { + custom: "my_widget", + "Example" => ExampleAction, + "Example2" => ExampleAction, + "Example toggle" => ExampleU8Action(1_u8), + section! { + "Section example" => ExampleAction, + "Example toggle" => ExampleU8Action(1_u8), + }, + section! { + "Example" => ExampleAction, + "Example2" => ExampleAction, + "Example Value" => ExampleU8Action(1_u8), + }, + "submenu1" { + "Example" => ExampleAction, + "Example2" => ExampleAction, + "Example toggle" => ExampleU8Action(1_u8), + "submenu2" { + "Example" => ExampleAction, + "Example2" => ExampleAction, + "Example toggle" => ExampleU8Action(1_u8), + "submenu3" { + "Example" => ExampleAction, + "Example2" => ExampleAction, + "Example toggle" => ExampleU8Action(1_u8), + } + } + } + } + }; + + let app = relm4::main_application(); + app.set_menubar(Some(&main_menu)); + let model = AppModel { mode: AppMode::View, control: control, diff --git a/src/coords/mapper.rs b/src/coords/mapper.rs index b846b90..5538cd8 100644 --- a/src/coords/mapper.rs +++ b/src/coords/mapper.rs @@ -49,7 +49,7 @@ impl Mapper { pub fn fore_map(&self, coord: WindowCoord) -> Result<(f64, f64), ProjError> { let (x, y) = coord; let c = (x as f64) * (self.bounds.1 - self.bounds.0) + self.bounds.0; - let d = (y as f64) * (self.bounds.3 - self.bounds.2) + self.bounds.2; + let d = ((1.0 - y) as f64) * (self.bounds.3 - self.bounds.2) + self.bounds.2; let (lon, lat) = self.proj.project((c, d), true)?; Ok((lon.to_degrees(), lat.to_degrees())) } @@ -75,7 +75,7 @@ impl Mapper { let x = (p1 - self.bounds.0) / (self.bounds.1 - self.bounds.0); let y = (p2 - self.bounds.2) / (self.bounds.3 - self.bounds.2); - Ok((x, y)) + Ok((x, (1.0 - y))) } pub fn set_lon_range(&mut self, range: std::ops::Range) -> &mut Self { diff --git a/src/main.rs b/src/main.rs index 84594da..58e95e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,6 +8,7 @@ use gtk::prelude::*; use gtk::{gio, glib, Application, ApplicationWindow}; use relm4::RelmApp; use std::ptr; +use relm4::menu; mod components; mod coords; mod data; @@ -50,8 +51,7 @@ fn main() { // app.connect_activate(build_ui); // // Run the application // app.run() - - let relm = RelmApp::new(APP_ID); + let relm = relm4::RelmApp::new(APP_ID); relm.run::(AppMode::Edit); } diff --git a/src/monitor/mod.rs b/src/monitor/mod.rs index 8223504..ef59eb5 100644 --- a/src/monitor/mod.rs +++ b/src/monitor/mod.rs @@ -23,6 +23,9 @@ impl Monitor { pointer_location_detecture.connect_motion( clone!(@weak this as s => move |_context, x, y| { s.imp().renderer.borrow_mut().change_pointer(x as f32, y as f32); + let c = s.imp().renderer.borrow(); + let cc = c.imp().config.borrow(); + println!("pointer location: {},{}", cc.pointer_lon_lat.0, cc.pointer_lon_lat.1); } ), ); @@ -43,7 +46,7 @@ impl Monitor { }); r.set_translate(( px as f32 * (scale - 1.0), - py as f32 * (scale - 1.0) + (1.0-py) as f32 * (scale - 1.0) )); r.queue_render(); Inhibit(false) diff --git a/src/render/exterior/imp.rs b/src/render/exterior/imp.rs new file mode 100644 index 0000000..5e4272d --- /dev/null +++ b/src/render/exterior/imp.rs @@ -0,0 +1,17 @@ +use geo_types::MultiPolygon; +use gtk::glib; +use gtk::subclass::prelude::*; +use std::cell::RefCell; + + +#[derive(Default)] +pub struct ExteriorWidget { +} + +#[glib::object_subclass] +impl ObjectSubclass for ExteriorWidget { + const NAME: &'static str = "ExteriorWidget"; + type Type = super::ExteriorWidget; +} + +impl ObjectImpl for ExteriorWidget{} diff --git a/src/render/exterior/mod.rs b/src/render/exterior/mod.rs new file mode 100644 index 0000000..ce2f0b9 --- /dev/null +++ b/src/render/exterior/mod.rs @@ -0,0 +1,38 @@ +mod imp; +use crate::coords::{Mapper, Range}; +use femtovg::{renderer::OpenGl, Canvas, Color, Paint, Path}; +use geo_types::{line_string, LineString, Point}; +use glib::subclass::types::ObjectSubclassIsExt; +use std::cell::Ref; + +glib::wrapper! { + pub struct ExteriorWidget(ObjectSubclass); +} + +impl Default for ExteriorWidget { + fn default() -> Self { + Self::new() + } +} + +impl ExteriorWidget { + pub fn new() -> Self { + let this: Self = glib::Object::new(); + this + } + + pub(super) fn draw(&self, canvas: &mut Canvas, mapper: Ref<'_, Mapper>) { + let imp = self.imp(); + let canvas_width = canvas.width(); + let canvas_height = canvas.height(); + let padding = [30.0,30.0,30.0,30.0]; + + let w = canvas_width - padding[1] - padding[3]; + let h = canvas_height - padding[0] - padding[2]; + + let paint = Paint::color(Color::white()); + let mut path = Path::new(); + path.rect(padding[3], padding[0], w, h); + canvas.stroke_path(&path, &paint); + } +} diff --git a/src/render/imp.rs b/src/render/imp.rs index f5d9e9c..0e0f91c 100644 --- a/src/render/imp.rs +++ b/src/render/imp.rs @@ -1,9 +1,10 @@ use super::background::BackgroundWidget; +use super::exterior::ExteriorWidget; use super::foreground::ForegroundWidget; use super::WindowCoord; use crate::coords::proj::Mercator; use crate::coords::Mapper; -use femtovg::{Color, FontId, Paint, Path}; +use femtovg::{Color, FontId, Paint, Path, Transform2D}; use gtk::glib; use gtk::prelude::WidgetExtManual; use gtk::subclass::prelude::*; @@ -32,6 +33,7 @@ struct Fonts { pub struct Render { pub(super) background: RefCell, pub(super) foreground: RefCell, + pub(super) exterior: RefCell, pub config: RefCell, pub mapper: RefCell, pub(super) canvas: RefCell>>, @@ -42,6 +44,7 @@ impl Default for Render { Self { background: RefCell::new(BackgroundWidget::default()), foreground: RefCell::new(ForegroundWidget::default()), + exterior: RefCell::new(ExteriorWidget::default()), config: RefCell::new(RenderConfig::default()), mapper: RefCell::new(Mercator::new().into()), canvas: RefCell::new(None), @@ -94,6 +97,7 @@ impl GLAreaImpl for Render { let w = canvas.width(); let h = canvas.height(); let configs = self.config.borrow(); + canvas.clear_rect( 0, 0, @@ -101,30 +105,32 @@ impl GLAreaImpl for Render { (h as i32 * dpi) as u32, Color::rgba(0, 0, 0, 255), ); - let mapper = self.mapper.borrow(); - let (lon_range, lat_range) = mapper.range.clone(); - { - let background_widget = self.background.borrow_mut(); - background_widget.set_lat_lines(lat_range.key_points(9)); - } - { - let background_widget = self.background.borrow_mut(); - background_widget.set_lon_lines(lon_range.key_points(20)); - } - let translate = self.translate(); - self.foreground - .borrow() - .draw(canvas, configs.scale, dpi, self.mapper.borrow()); - self.background.borrow().draw( - canvas, - configs.scale, - dpi, - translate, - self.mapper.borrow(), - (lon_range, lat_range), - ); + let (lon_range, lat_range) = mapper.range.clone(); + // { + // let background_widget = self.background.borrow_mut(); + // background_widget.set_lat_lines(lat_range.key_points(9)); + // } + // { + // let background_widget = self.background.borrow_mut(); + // background_widget.set_lon_lines(lon_range.key_points(20)); + // } + let translate = self.translate(); + + self.exterior.borrow().draw(canvas,self.mapper.borrow()); + // self.foreground + // .borrow() + // .draw(canvas, configs.scale, dpi, self.mapper.borrow()); + + // self.background.borrow().draw( + // canvas, + // configs.scale, + // dpi, + // translate, + // self.mapper.borrow(), + // (lon_range, lat_range), + // ); canvas.flush(); true } diff --git a/src/render/mod.rs b/src/render/mod.rs index aadc23a..b3c32ba 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -1,5 +1,6 @@ mod background; mod foreground; +mod exterior; mod imp; use crate::coords::Mapper; use crate::data::{MultiDimensionData, RadarData2d}; @@ -8,6 +9,7 @@ use crate::pipeline::{Pipeline, ShadePipe}; use std::fmt::Debug; pub use self::background::{BackgroundConfig, BackgroundWidget}; +use self::exterior::ExteriorWidget; pub use self::foreground::{ForegroundConfig, ForegroundWidget}; use self::imp::RenderConfig; use crate::data::DownSampleMeth;