207 lines
6.1 KiB
Rust
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();
|
|
}
|
|
}
|