mod cms; mod exterior; mod imp; mod interior; pub mod predefined; pub mod renders; pub mod widget; // pub use self::cms::CMS; use crate::coords::cms::CMS; pub use self::imp::{RenderConfig, RenderMotion, RenderStatus}; use crate::coords::Mapper; use adw::prelude::{GLAreaExt, GestureDragExt}; use geo_types::LineString; use glib::clone; pub use glib::subclass::prelude::*; use gtk::traits::WidgetExt; use gtk::{EventControllerScrollFlags, Inhibit}; pub use interior::*; use std::cell::{Ref, RefCell, RefMut}; use std::rc::Rc; use std::sync::{Arc, Mutex}; pub type WindowCoord = (f32, f32); glib::wrapper! { pub struct Render(ObjectSubclass) @extends gtk::GLArea, gtk::Widget; } impl Default for Render { fn default() -> Self { Self::new(None, RenderConfig { padding: [10.0; 4] }) } } impl Render { pub fn new(mapper: Option, cfg: RenderConfig) -> Self { let this: Self = glib::Object::new(); { let mut status = this.imp().status.borrow_mut(); status.scale = 1.0; } this.imp().config.replace(cfg); if let Some(mapper) = mapper { this.set_mapper(mapper); } let pointer_location_detecture = gtk::EventControllerMotion::new(); pointer_location_detecture.connect_motion( clone!( @weak this as r => move |_context, x, y| { let dpi = r.scale_factor(); r.update_status(|s| { let (_,h) = s.window_size.unwrap(); s.pointer_location = (x as f32 * dpi as f32, h as f32 - y as f32 * dpi as f32); }); } ), ); let scale_detecture = gtk::EventControllerScroll::new(EventControllerScrollFlags::VERTICAL); scale_detecture.connect_scroll(clone!( @weak this as r => @default-panic,move |_context, _x, y| { r.update_status(|status|{ status.scale = y as f32; status.motion = RenderMotion::Scale; }); r.queue_render(); Inhibit(false) } )); let drag_detecture = gtk::GestureDrag::new(); drag_detecture.connect_drag_update(clone!( @weak this as r => move |this, _, _| { let (ox, oy) = this.offset().unwrap_or((0.0,0.0)); let dpi = r.scale_factor() as f32; r.update_status(|s| { s.translate = Some((-ox as f32 * dpi , oy as f32 * dpi)); s.motion = RenderMotion::Translate; }); r.queue_render(); })); drag_detecture.connect_drag_end(clone!( @weak this as r => move |_,_,_|{ r.update_status(|cfg| { cfg.translate = None; cfg.motion = RenderMotion::Translate; }) } r.queue_render(); )); this.set_hexpand(true); this.set_vexpand(true); this.add_controller(pointer_location_detecture); this.add_controller(scale_detecture); this.add_controller(drag_detecture); this } pub fn change_cfg(&self, mut f: F) where F: FnMut(&mut RenderConfig), { let mut cfg = self.imp().config.borrow_mut(); f(&mut cfg); } pub fn get_canvas(&self) -> RefMut<'_, Option>> { self.imp().canvas.borrow_mut() } pub fn set_cfg(&self, cfg: RenderConfig) { self.imp().config.replace(cfg); } pub fn update_status(&self, mut f: F) where F: FnMut(&mut RenderStatus), { let mut status = self.imp().status.borrow_mut(); f(&mut status); } pub fn set_mapper(&self, mapper: Mapper) { self.imp().mapper.replace(mapper); } pub fn set_interior_layers(&self, layers: Rc>>) { self.imp().interior_layers.replace(layers); self.queue_render(); self.set_render_status(0); } pub fn map(&self, loc: (f64, f64)) -> Option<(f32, f32)> { let foremapped = self.get_mapper().map(loc).unwrap(); return self.imp().map(foremapped); } pub fn inverse_map(&self, loc: (f32, f32)) -> Option<(f64, f64)> { let foremapped = self.imp().inverse_map(loc); foremapped.and_then(|foremapped| self.get_mapper().inverse_map(foremapped).ok()) } pub fn ring_map(&self, ring: &LineString) -> Option> { Some( ring.points() .into_iter() .map(|p| self.map((p.x(), p.y()))) .filter(|p| p.is_some()) .collect::>>() .unwrap() .into(), ) } pub fn point_in_bound(&self, loc: (f64, f64)) -> bool { self.get_mapper().point_in_bound(loc) } fn get_mapper(&self) -> Ref { self.imp().mapper.borrow() } pub fn window_size(&self) -> (i32, i32) { self.imp().window_size().unwrap() } pub fn create_drawer(&self, range: (f64, f64, f64, f64), window_size: (f32, f32), mut f: F) where F: FnMut(&CMS), { let (lon1, lon2, lat1, lat2) = range; let mut mapper = self.get_mapper().clone(); mapper.set_lat_range(lat1..lat2); mapper.set_lon_range(lon1..lon2); let cms = CMS::new(mapper, window_size); f(&cms); } pub fn pointer_loc(&self, transed: bool) -> (f64, f64) { let raw = self.imp().status.borrow().pointer_location.clone(); if transed { self.inverse_map(raw).unwrap() } else { (raw.0 as f64, raw.1 as f64) } } pub fn render_range(&self) -> ((f64, f64), (f64, f64)) { self.imp().view_range().unwrap() } pub fn create_cms(&self) -> CMS { let borrowed_mapper = &*self.imp().mapper.borrow(); let new_mapper = borrowed_mapper.clone(); CMS::new(new_mapper, (500.0, 500.0)) } pub fn set_view(&self, range: (f64, f64, f64, f64)) { self.imp().set_view(range); self.queue_render(); } }