radar-g/src/widgets/render/mod.rs
2024-03-06 12:13:21 +08:00

207 lines
6.1 KiB
Rust

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<imp::Render>)
@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<Mapper>, 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<F>(&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<femtovg::Canvas<femtovg::renderer::OpenGl>>> {
self.imp().canvas.borrow_mut()
}
pub fn set_cfg(&self, cfg: RenderConfig) {
self.imp().config.replace(cfg);
}
pub fn update_status<F>(&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<RefCell<Vec<Layer>>>) {
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<f64>) -> Option<LineString<f32>> {
Some(
ring.points()
.into_iter()
.map(|p| self.map((p.x(), p.y())))
.filter(|p| p.is_some())
.collect::<Option<Vec<_>>>()
.unwrap()
.into(),
)
}
pub fn point_in_bound(&self, loc: (f64, f64)) -> bool {
self.get_mapper().point_in_bound(loc)
}
fn get_mapper(&self) -> Ref<Mapper> {
self.imp().mapper.borrow()
}
pub fn window_size(&self) -> (i32, i32) {
self.imp().window_size().unwrap()
}
pub fn create_drawer<F>(&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();
}
}