sync
This commit is contained in:
parent
caf8b68926
commit
b21529c2b9
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -550,6 +550,7 @@ dependencies = [
|
||||
"tracing",
|
||||
"tracing-subscriber",
|
||||
"tracker",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@ -92,6 +92,7 @@ imgref = "1.10.1"
|
||||
rgb = "0.8.37"
|
||||
slippy-map-tiles = "0.16.0"
|
||||
reqwest = "0.11.25"
|
||||
url = "2.5.0"
|
||||
|
||||
|
||||
[build-dependencies]
|
||||
|
||||
@ -10,12 +10,9 @@ pub enum MonitorInputMsg {
|
||||
NewElement((ElementKey, ElementID)),
|
||||
AddWidget(Box<dyn Widget>),
|
||||
RemoveWidget,
|
||||
AddLayer(Layer),
|
||||
RemoveLayer(String),
|
||||
AddMetaItem(HashMap<String, String>),
|
||||
ClearMetaItems,
|
||||
UpdateMetaItem(HashMap<String, String>),
|
||||
UpdateLayer((String, Box<dyn Fn(&mut Layer) + 'static>)),
|
||||
RefreshLayerList,
|
||||
SetRenderRange(f64, f64, f64, f64),
|
||||
None,
|
||||
@ -27,9 +24,6 @@ impl Debug for MonitorInputMsg {
|
||||
MonitorInputMsg::SetRenderRange(_, _, _, _) => write!(f, "MonitorInputMsg::SetRenderRange"),
|
||||
MonitorInputMsg::RefreshLayerList => write!(f, "MonitorInputMsg::RefreshLayerList"),
|
||||
MonitorInputMsg::NewElement(_) => write!(f, "MonitorInputMsg::NewElement"),
|
||||
MonitorInputMsg::AddLayer(_) => write!(f, "MonitorInputMsg::AddLayer"),
|
||||
MonitorInputMsg::RemoveLayer(_) => write!(f, "MonitorInputMsg::RemoveLayer"),
|
||||
MonitorInputMsg::UpdateLayer(_) => write!(f, "MonitorInputMsg::UpdateLayer"),
|
||||
MonitorInputMsg::None => write!(f, "MonitorInputMsg::None"),
|
||||
MonitorInputMsg::AddWidget(_) => write!(f, "MonitorInputMsg::AddWidget"),
|
||||
MonitorInputMsg::RemoveWidget => write!(f, "MonitorInputMsg::RemoveWidget"),
|
||||
|
||||
@ -18,13 +18,20 @@ use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use tokio::task;
|
||||
use super::sidebar::{sidebar::SideBarModel, SideBarInputMsg, SideBarOutputMsg};
|
||||
use crate::map_tile::MapTile;
|
||||
use adw::prelude::*;
|
||||
use femtovg::ImageId;
|
||||
use relm4::{component::Component, *};
|
||||
use slippy_map_tiles::Tile;
|
||||
use tracing::instrument::WithSubscriber;
|
||||
use crate::coords::Range;
|
||||
use crate::pipeline::element::Target;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MonitorCommand {
|
||||
// NewLayer(Layer),
|
||||
LoadTile(Tile, Vec<u8>, (f64,f64), (Range, Range)),
|
||||
None,
|
||||
}
|
||||
#[tracker::track]
|
||||
@ -33,6 +40,10 @@ pub struct MonitorModel {
|
||||
render_range: (f64, f64, f64, f64),
|
||||
sidebar_open: bool,
|
||||
sidebar_width: i32,
|
||||
#[do_not_track]
|
||||
map_tile_getter: Arc<MapTile>,
|
||||
#[do_not_track]
|
||||
tiles: Rc<RefCell<HashMap<Tile, Target>>>,
|
||||
new_layer: i8,
|
||||
#[no_eq]
|
||||
widgets: Vec<WidgetFrame>,
|
||||
@ -86,6 +97,37 @@ impl Component for MonitorModel {
|
||||
connect_render_status_notify[sender] => move |r| {
|
||||
sender.output(MonitorOutputMsg::LayerRenderFinished);
|
||||
},
|
||||
set_tiles: model.tiles.clone(),
|
||||
connect_range_changing_notify[sender] => move |r| {
|
||||
let ((x1 , x2), (y1,y2))= r.render_range();
|
||||
let w = r.width() as f32;
|
||||
let h = r.height() as f32;
|
||||
let map_tile_getter = map_tile_getter.clone();
|
||||
let new_tiles = map_tile_getter.new_tiles(3 ,(y1 as f32,y2 as f32),(x1 as f32,x2 as f32));
|
||||
|
||||
let tiles = (*tiles).borrow();
|
||||
let new_tiles = new_tiles.filter(|x| !tiles.contains_key(x)).collect::<Vec<_>>();
|
||||
|
||||
if new_tiles.len() > 0 {
|
||||
let new_sender = sender.clone();
|
||||
sender.oneshot_command(async move {
|
||||
for tile in new_tiles {
|
||||
let map_tile_getter = map_tile_getter.clone();
|
||||
let sender = new_sender.clone();
|
||||
task::spawn(async move {
|
||||
let result = map_tile_getter.get_tile(&tile).await;
|
||||
if let Ok(result) = result {
|
||||
let origin = tile.nw_corner();
|
||||
let rb = tile.se_corner();
|
||||
let bounds = ((origin.lon() as f64..rb.lon() as f64).into(), (origin.lat() as f64..rb.lat() as f64).into());
|
||||
sender.command_sender().emit(MonitorCommand::LoadTile(tile, result,(origin.lon() as f64, origin.lat() as f64), bounds));
|
||||
}
|
||||
});
|
||||
}
|
||||
MonitorCommand::None
|
||||
});
|
||||
}
|
||||
},
|
||||
set_interior_layers: model.layers.clone(),
|
||||
},
|
||||
add_overlay=>k::Button{
|
||||
@ -107,15 +149,16 @@ impl Component for MonitorModel {
|
||||
}
|
||||
}
|
||||
|
||||
fn update_with_view(&mut self, widgets: &mut Self::Widgets, message: Self::Input, sender: ComponentSender<Self>, root: &Self::Root) {
|
||||
fn update_with_view(
|
||||
&mut self,
|
||||
widgets: &mut Self::Widgets,
|
||||
message: Self::Input,
|
||||
sender: ComponentSender<Self>,
|
||||
root: &Self::Root,
|
||||
) {
|
||||
self.reset();
|
||||
match message {
|
||||
MonitorInputMsg::AddLayer(layer) => {
|
||||
self.layers.borrow_mut().push(layer);
|
||||
let raw_id = self.get_new_layer();
|
||||
self.set_new_layer(*raw_id + 1);
|
||||
self.sidebar.sender().send(SideBarInputMsg::RefreshList);
|
||||
}
|
||||
|
||||
MonitorInputMsg::RefreshLayerList => {
|
||||
self.sidebar.sender().send(SideBarInputMsg::RefreshList);
|
||||
widgets.renderer.queue_render();
|
||||
@ -123,8 +166,8 @@ impl Component for MonitorModel {
|
||||
MonitorInputMsg::AddMetaItem(map) => {
|
||||
self.sidebar.emit(SideBarInputMsg::AddMetaItems(map))
|
||||
}
|
||||
MonitorInputMsg::SetRenderRange(lon_start,lon_end,lat_start,lat_end)=>{
|
||||
self.set_render_range((lat_start,lat_end,lon_start,lon_end));
|
||||
MonitorInputMsg::SetRenderRange(lon_start, lon_end, lat_start, lat_end) => {
|
||||
self.set_render_range((lat_start, lat_end, lon_start, lon_end));
|
||||
}
|
||||
MonitorInputMsg::ClearMetaItems => self.sidebar.emit(SideBarInputMsg::ClearMetaItems),
|
||||
MonitorInputMsg::UpdateMetaItem(map) => {
|
||||
@ -157,7 +200,6 @@ impl Component for MonitorModel {
|
||||
let sidebar: Controller<SideBarModel> = SideBarModel::builder()
|
||||
.launch(init.clone())
|
||||
.forward(sender.input_sender(), move |msg| match msg {
|
||||
SideBarOutputMsg::NewLayer(layer) => MonitorInputMsg::AddLayer(layer),
|
||||
SideBarOutputMsg::SwitchToTimeSeries(layer) => {
|
||||
sidebar_sender.output(MonitorOutputMsg::LayerSwitchToTime(layer));
|
||||
MonitorInputMsg::None
|
||||
@ -173,27 +215,39 @@ impl Component for MonitorModel {
|
||||
render_range: (4.0, 53.3, 73.3, 135.0),
|
||||
new_layer: 0,
|
||||
widgets: vec![],
|
||||
tiles: Rc::new(RefCell::new(HashMap::new())),
|
||||
render_cfg,
|
||||
sidebar_open: true,
|
||||
sidebar_width: 400,
|
||||
layers: init,
|
||||
map_tile_getter: Arc::new(MapTile::default()),
|
||||
sidebar,
|
||||
tracker: 0,
|
||||
};
|
||||
|
||||
let map_tile_getter = model.map_tile_getter.clone();
|
||||
let tiles = model.tiles.clone();
|
||||
|
||||
let widgets = view_output! {};
|
||||
ComponentParts { model, widgets }
|
||||
}
|
||||
|
||||
fn update_cmd(
|
||||
fn update_cmd_with_view(
|
||||
&mut self,
|
||||
msg: Self::CommandOutput,
|
||||
_sender: ComponentSender<Self>,
|
||||
_root: &Self::Root,
|
||||
widgets: &mut Self::Widgets,
|
||||
message: Self::CommandOutput,
|
||||
sender: ComponentSender<Self>,
|
||||
root: &Self::Root,
|
||||
) {
|
||||
self.reset();
|
||||
match msg {
|
||||
match message {
|
||||
MonitorCommand::LoadTile(key, ref tile, origin, bounds) => {
|
||||
let target = widgets.renderer.load_img_mem(&tile,origin,(256f32,256f32), bounds).unwrap();
|
||||
self.tiles.borrow_mut().insert(key, target);
|
||||
widgets.render.queue_draw();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
self.update_view(widgets, sender);
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,6 +28,7 @@ mod widgets;
|
||||
mod data_utils;
|
||||
mod predefined;
|
||||
mod map_tile_utils;
|
||||
mod map_tile;
|
||||
|
||||
const APP_ID: &str = "org.tsuki.radar_g";
|
||||
static RUNTIME: SafeLazy<Runtime> =
|
||||
|
||||
54
src/map_tile.rs
Normal file
54
src/map_tile.rs
Normal file
@ -0,0 +1,54 @@
|
||||
use crate::map_tile_utils::lat_lon_to_zoom;
|
||||
use femtovg::ImageSource;
|
||||
use reqwest::{Client, Error, Url};
|
||||
use slippy_map_tiles::{BBox, merc_location_to_tile_coords, Tile};
|
||||
use crate::coords::Range;
|
||||
|
||||
pub struct MapTile {
|
||||
server: String,
|
||||
api_key: String,
|
||||
style: String,
|
||||
client: Client,
|
||||
}
|
||||
|
||||
impl Default for MapTile{
|
||||
fn default() -> Self {
|
||||
Self{
|
||||
server: "https://tiles.stadiamaps.com/tiles/".to_string(),
|
||||
api_key: "06f1aeed-5d91-48e3-9ce5-1e99063f7f73".to_string(),
|
||||
style: "stamen_toner/".to_string(),
|
||||
client: Client::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MapTile {
|
||||
|
||||
pub fn new_tiles(&self, zoom: u8, lat_range: (f32, f32), lon_range: (f32, f32)) -> impl Iterator<Item = Tile> + Sized {
|
||||
let bbox= BBox::new(lat_range.1 , lon_range.0, lat_range.0, lon_range.1).unwrap();
|
||||
let tiles = bbox.tiles_for_zoom(zoom);
|
||||
tiles
|
||||
}
|
||||
pub async fn get_tile(
|
||||
&self,
|
||||
tile: &Tile
|
||||
) -> Result<Vec<u8>, Error>
|
||||
{
|
||||
let base_url = Url::parse(&self.server).unwrap();
|
||||
// let zoom = lat_lon_to_zoom(lat_range, lat_range, w, h);
|
||||
let mut request_url = base_url
|
||||
.join(&self.style)
|
||||
.unwrap()
|
||||
.join(&format!("{}/{}/{}.png", tile.zoom(), tile.x(), tile.y()))
|
||||
.unwrap();
|
||||
|
||||
let result = self
|
||||
.client
|
||||
.get(request_url)
|
||||
.query(&[("api_key", &self.api_key)])
|
||||
.send()
|
||||
.await?;
|
||||
let bytes = result.bytes().await?;
|
||||
Ok(bytes.to_vec())
|
||||
}
|
||||
}
|
||||
@ -1 +1 @@
|
||||
mod map_tile;
|
||||
pub mod map_tile;
|
||||
@ -3,7 +3,6 @@ use gtk::glib;
|
||||
use gtk::subclass::prelude::*;
|
||||
use std::cell::RefCell;
|
||||
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ExteriorWidget {
|
||||
}
|
||||
|
||||
@ -3,14 +3,17 @@ use super::interior::InteriorWidget;
|
||||
use super::{Layer, WindowCoord};
|
||||
use crate::coords::proj::Mercator;
|
||||
use crate::coords::Mapper;
|
||||
use crate::pipeline::element::Target;
|
||||
use femtovg::{Canvas, Color, FontId, Renderer};
|
||||
use gtk::glib::{self, prelude::*, Properties};
|
||||
use gtk::subclass::prelude::*;
|
||||
use gtk::traits::{GLAreaExt, WidgetExt};
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::HashMap;
|
||||
use std::num::NonZeroU32;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use slippy_map_tiles::Tile;
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq)]
|
||||
pub struct RenderConfig {
|
||||
@ -48,10 +51,13 @@ pub struct RenderStatus {
|
||||
pub struct Render {
|
||||
#[property(get, set)]
|
||||
render_status: Cell<i64>,
|
||||
#[property(get, set)]
|
||||
range_changing: Cell<f64>,
|
||||
pub(super) exterior: RefCell<ExteriorWidget>,
|
||||
pub(super) interior: RefCell<InteriorWidget>,
|
||||
pub(super) canvas: RefCell<Option<femtovg::Canvas<femtovg::renderer::OpenGl>>>,
|
||||
pub(super) glow_context: RefCell<Option<glow::Context>>,
|
||||
pub(super) tiles: RefCell<Rc<RefCell<HashMap<Tile, Target>>>>,
|
||||
pub config: RefCell<RenderConfig>,
|
||||
pub status: RefCell<RenderStatus>,
|
||||
pub mapper: RefCell<Mapper>,
|
||||
@ -61,6 +67,7 @@ pub struct Render {
|
||||
impl Default for Render {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
range_changing: Cell::new(0.0),
|
||||
render_status: Cell::new(0),
|
||||
exterior: RefCell::new(ExteriorWidget::default()),
|
||||
interior: RefCell::new(InteriorWidget::default()),
|
||||
@ -68,6 +75,7 @@ impl Default for Render {
|
||||
interior_layers: RefCell::new(Rc::new(RefCell::new(Vec::new()))),
|
||||
config: RefCell::new(RenderConfig::default()),
|
||||
status: RefCell::new(RenderStatus::default()),
|
||||
tiles: RefCell::new(Rc::new(RefCell::new(HashMap::new()))),
|
||||
mapper: RefCell::new(Mercator::default().into()),
|
||||
canvas: RefCell::new(None),
|
||||
}
|
||||
@ -152,6 +160,12 @@ impl GLAreaImpl for Render {
|
||||
(w, h)
|
||||
};
|
||||
|
||||
let tiles = self.tiles.borrow().borrow();
|
||||
|
||||
for tile in tiles.values() {
|
||||
|
||||
}
|
||||
|
||||
let render_range = self.status.borrow().view_range.clone();
|
||||
if let Some(((lat1, lat2), (lon1, lon2))) = render_range {
|
||||
let mut status = self.status.borrow_mut();
|
||||
|
||||
@ -2,7 +2,7 @@ use super::super::WindowCoord;
|
||||
use gtk::glib;
|
||||
use gtk::subclass::prelude::*;
|
||||
use std::cell::RefCell;
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
use super::layers::Layer;
|
||||
|
||||
#[derive(Default)]
|
||||
|
||||
@ -1,30 +0,0 @@
|
||||
pub(super) struct MapTile {
|
||||
server: Option<String>,
|
||||
lat_range: (f64, f64),
|
||||
lon_range: (f64, f64),
|
||||
zoom: u8,
|
||||
}
|
||||
|
||||
impl MapTile{
|
||||
pub fn new(server: Option<String>, lat_range: (f64, f64), lon_range: (f64, f64), zoom: u8) -> MapTile {
|
||||
MapTile {
|
||||
server,
|
||||
lat_range,
|
||||
lon_range,
|
||||
zoom,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_server(&self) -> Option<String> {
|
||||
self.server.clone()
|
||||
}
|
||||
|
||||
pub fn get_lat_range(&self) -> (f64, f64) {
|
||||
self.lat_range
|
||||
}
|
||||
|
||||
pub fn get_lon_range(&self) -> (f64, f64) {
|
||||
self.lon_range
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,18 @@
|
||||
mod imp;
|
||||
mod layers;
|
||||
mod map_tile;
|
||||
|
||||
use gtk::subclass::prelude::ObjectSubclassIsExt;
|
||||
|
||||
use super::super::Render;
|
||||
use femtovg::{renderer::OpenGl, Canvas};
|
||||
pub use layers::{Layer, LayerImpl, LayerImplSync, AssoElement};
|
||||
use crate::RUNTIME;
|
||||
use core_extensions::SelfOps;
|
||||
use femtovg::{renderer::OpenGl, Canvas, ImageFlags};
|
||||
use femtovg::{Paint, Path};
|
||||
pub use layers::{AssoElement, Layer, LayerImpl, LayerImplSync};
|
||||
use relm4::channel;
|
||||
use std::cell::Ref;
|
||||
use tokio::task;
|
||||
use tokio::task::LocalSet;
|
||||
|
||||
use super::imp::{RenderConfig, RenderStatus};
|
||||
|
||||
|
||||
@ -8,7 +8,7 @@ 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 crate::coords::{Mapper, Range};
|
||||
use adw::prelude::{GLAreaExt, GestureDragExt};
|
||||
use geo_types::LineString;
|
||||
use glib::clone;
|
||||
@ -17,8 +17,13 @@ use gtk::traits::WidgetExt;
|
||||
use gtk::{EventControllerScrollFlags, Inhibit};
|
||||
pub use interior::*;
|
||||
use std::cell::{Ref, RefCell, RefMut};
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use femtovg::ImageFlags;
|
||||
use slippy_map_tiles::Tile;
|
||||
use crate::errors::PipelineError;
|
||||
use crate::pipeline::element::{Target, TargetType};
|
||||
|
||||
pub type WindowCoord = (f32, f32);
|
||||
|
||||
@ -64,6 +69,7 @@ impl Render {
|
||||
status.scale = y as f32;
|
||||
status.motion = RenderMotion::Scale;
|
||||
});
|
||||
r.set_range_changing(0.0);
|
||||
r.queue_render();
|
||||
Inhibit(false)
|
||||
}
|
||||
@ -78,6 +84,7 @@ impl Render {
|
||||
s.translate = Some((-ox as f32 * dpi , oy as f32 * dpi));
|
||||
s.motion = RenderMotion::Translate;
|
||||
});
|
||||
r.set_range_changing(0.0);
|
||||
r.queue_render();
|
||||
}));
|
||||
|
||||
@ -205,6 +212,21 @@ impl Render {
|
||||
|
||||
pub fn set_view(&self, range: (f64, f64, f64, f64)) {
|
||||
self.imp().set_view(range);
|
||||
self.set_range_changing(range.0 + range.1);
|
||||
// self.set_range(range);
|
||||
self.queue_render();
|
||||
}
|
||||
|
||||
pub fn set_tiles(&self, tiles: Rc<RefCell<HashMap<Tile, Target>>>) {
|
||||
self.imp().tiles.replace(tiles);
|
||||
self.queue_render();
|
||||
}
|
||||
|
||||
pub fn load_img_mem(&self, img: &[u8], origin:(f64,f64),size :(f32,f32), bounds: (Range, Range)) -> Result<Target, PipelineError> {
|
||||
let mut canvas = self.get_canvas();
|
||||
let cvs = canvas.as_mut().unwrap();
|
||||
let img_id = cvs.load_image_mem(img, ImageFlags::empty()).unwrap();
|
||||
let (width, height) = size;
|
||||
Ok(Target::new(TargetType::ImageId(img_id), width, height, bounds, None, None))
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user