diff --git a/src/components/control_panel/control_panel.rs b/src/components/control_panel/control_panel.rs index 98ab52c..6dbc741 100644 --- a/src/components/control_panel/control_panel.rs +++ b/src/components/control_panel/control_panel.rs @@ -1,6 +1,7 @@ use crate::timeline::TimeLine; use adw::prelude::*; use chrono::{prelude::*, DateTime, Duration, TimeZone, Utc}; +use gtk::glib::clone; use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt, ToggleButtonExt}; use relm4::typed_list_view::{RelmListItem, TypedListView}; use relm4::*; @@ -78,6 +79,7 @@ pub enum HeaderOutput { pub enum TimelineMsg { Rewind(Duration), FastForward(Duration), + SetStart(DateTime), } #[derive(Debug)] @@ -85,6 +87,8 @@ pub enum AppMsg { Open(PathBuf), TimeLine(TimelineMsg), Selection(Option>), + SelectionRewind, + SelectionFastForward, } #[relm4::component(pub)] @@ -131,13 +135,19 @@ impl SimpleComponent for ControlPanelModel { set_orientation: gtk::Orientation::Horizontal, set_spacing:10, gtk::Button{ - set_icon_name: "rewind-filled" + set_icon_name: "rewind-filled", + connect_clicked[sender] => move |_| { + sender.input(AppMsg::SelectionRewind); + }, }, gtk::Button{ set_icon_name: "play-filled" }, gtk::Button{ - set_icon_name: "fast-forward-filled" + set_icon_name: "fast-forward-filled", + connect_clicked[sender] => move |_| { + sender.input(AppMsg::SelectionFastForward); + }, } } @@ -157,8 +167,37 @@ impl SimpleComponent for ControlPanelModel { gtk::Box{ set_orientation: gtk::Orientation::Horizontal, set_spacing:5, + + #[name="pop"] + gtk::Popover{ + set_position: gtk::PositionType::Bottom, + set_pointing_to: Some(>k::gdk::Rectangle::new( + 0, + 0, + 80, + 40, + )), + gtk::Calendar{ + connect_day_selected[sender,pop] => move |cal| { + let date = cal.date().ymd(); + let date = Utc.with_ymd_and_hms(date.0, date.1 as u32, date.2 as u32, 0,0,0).unwrap(); + sender.input(AppMsg::TimeLine( + TimelineMsg::SetStart(date) + )); + pop.popdown(); + } + } + }, + gtk::Button{ + #[track = "model.changed(ControlPanelModel::timeline_start())"] + set_label:&model.timeline_start.format("%Y-%m-%d").to_string(), + connect_clicked[sender,pop] => move |_| { + pop.popup(); + }, + }, gtk::Button{ set_icon_name: "rewind-filled", + // add_controller: fastforward_long_press_detector, connect_clicked[sender] => move |_| { sender.input(AppMsg::TimeLine( TimelineMsg::Rewind(-Duration::minutes(12)) @@ -170,6 +209,8 @@ impl SimpleComponent for ControlPanelModel { set_width_request: 400, #[track = "model.changed(ControlPanelModel::timeline_start())"] set_time_start: model.timeline_start, + #[track = "model.changed(ControlPanelModel::selection())"] + set_selection: model.selection.map(|p| crate::timeline::Selection::Point(p)), connect_start_time_notify[sender] => move |time| { let time = time.start_time(); sender.input( @@ -211,8 +252,7 @@ impl SimpleComponent for ControlPanelModel { set_height_request: 140, set_width_request: 300, set_orientation:gtk::Orientation::Horizontal, - gtk::Calendar{ - } + } } }, @@ -239,11 +279,9 @@ impl SimpleComponent for ControlPanelModel { let mut list_img_wrapper: TypedListView = TypedListView::with_sorting(); - list_img_wrapper.append(ImgItem::new("00:00:00".to_string(), None, true)); let timeline_start = Utc::now(); - let model = ControlPanelModel { selection: None, timeline_start, @@ -266,10 +304,25 @@ impl SimpleComponent for ControlPanelModel { let current = self.get_timeline_start().clone(); self.set_timeline_start(current + c); } + TimelineMsg::SetStart(time) => { + self.set_timeline_start(time); + } }, AppMsg::Selection(selection) => { self.set_selection(selection); } + AppMsg::SelectionRewind => { + let current = self.get_selection().clone(); + if let Some(current) = current { + self.set_selection(Some(current - Duration::minutes(12))); + } + } + AppMsg::SelectionFastForward => { + let current = self.get_selection().clone(); + if let Some(current) = current { + self.set_selection(Some(current + Duration::minutes(12))); + } + } } } } diff --git a/src/components/render_panel/monitor/monitor.rs b/src/components/render_panel/monitor/monitor.rs index 2c7055b..80c475a 100644 --- a/src/components/render_panel/monitor/monitor.rs +++ b/src/components/render_panel/monitor/monitor.rs @@ -1,36 +1,32 @@ use crate::pipeline::offscreen_renderer::OffscreenRenderer; -use crate::render::{Target, CMS}; -// use crate::OFFSCREEN; +use crate::render::{RenderConfig, Target, CMS}; use crate::{ components::render_panel::messages::{MonitorInputMsg, MonitorOutputMsg}, coords::{proj::Mercator, Mapper}, - data::Npz, dynamic_col::DynamicCol, - render::{predefined::color_mapper::BoundaryNorm, Layer, Render}, - RUNTIME, + render::{Layer, Render}, }; use glib::clone; use std::sync::{Arc, Mutex}; use super::sidebar::{sidebar::SideBarModel, Msg, SideBarOutputMsg}; use adw::prelude::*; -use gtk::prelude::StyleContextExt; -use gtk::subclass::root; -use relm4::{ - component::{AsyncComponent, AsyncComponentParts, Component}, - loading_widgets::LoadingWidgets, - *, -}; +use relm4::{component::Component, *}; #[derive(Debug)] pub enum MonitorCommand { NewLayer(Layer), None, } +#[tracker::track] pub struct MonitorModel { + render_cfg: RenderConfig, + render_range: (f64, f64, f64, f64), sidebar_open: bool, sidebar_width: i32, + #[no_eq] layers: Vec, + #[no_eq] sidebar: Controller, } @@ -69,9 +65,12 @@ impl Component for MonitorModel { gtk::Overlay{ #[wrap(Some)] set_child = &Render{ - add_css_class: "rb", #[watch] set_interior_layers: model.layers.clone(), + #[track = "model.changed(MonitorModel::render_cfg())"] + set_cfg: model.render_cfg, + #[track = "model.changed(MonitorModel::render_range())"] + set_range: model.render_range, }, add_overlay=>k::Button{ set_label:"Add", @@ -160,11 +159,17 @@ impl Component for MonitorModel { SideBarOutputMsg::NewLayer(layer) => MonitorInputMsg::AddLayer(layer), _ => MonitorInputMsg::None, }); + + let render_cfg = RenderConfig { padding: [20.0; 4] }; + let model = MonitorModel { + render_range: (4.0, 53.3, 73.3, 135.0), + render_cfg, sidebar_open: true, sidebar_width: 400, layers: vec![], sidebar, + tracker: 0, }; let widgets = view_output! {}; @@ -177,12 +182,14 @@ impl Component for MonitorModel { _sender: ComponentSender, _root: &Self::Root, ) { + self.reset(); match msg { MonitorCommand::NewLayer(layer) => { self.layers.push(layer); + self.set_render_range((29.13, 30.16, 119.53, 121.13)); self.sidebar .sender() - .send(Msg::RefreshList(self.layers.clone())); + .send(Msg::RefreshList(self.layers.clone())).unwrap(); } _ => {} } diff --git a/src/render/imp.rs b/src/render/imp.rs index ddf3aab..41960b8 100644 --- a/src/render/imp.rs +++ b/src/render/imp.rs @@ -10,7 +10,7 @@ use gtk::traits::{GLAreaExt, WidgetExt}; use std::cell::RefCell; use std::num::NonZeroU32; -#[derive(Debug, Default, Clone)] +#[derive(Debug, Default, Clone, Copy, PartialEq)] pub struct RenderConfig { pub padding: [f32; 4], } diff --git a/src/render/mod.rs b/src/render/mod.rs index 269b202..2778a25 100644 --- a/src/render/mod.rs +++ b/src/render/mod.rs @@ -192,4 +192,13 @@ impl Render { let new_mapper = borrowed_mapper.clone(); CMS::new(new_mapper, (500.0, 500.0)) } + + pub fn set_range(&self, range: (f64, f64, f64, f64)) { + let (lat1, lat2, lon1, lon2) = range; + let mut mapper = self.imp().mapper.borrow_mut(); + println!("set range: {:?}", range); + mapper.set_lat_range(lat1..lat2); + mapper.set_lon_range(lon1..lon2); + self.queue_render(); + } } diff --git a/src/timeline/mod.rs b/src/timeline/mod.rs index 7ea5f25..8252196 100644 --- a/src/timeline/mod.rs +++ b/src/timeline/mod.rs @@ -73,6 +73,9 @@ impl TimeLine { let minor_tick_interval = major_tick_interval / (major_tick_step / minor_tick_step) as f64; let border_radius = self_.border_radius.get(); + self_.width.set(w as u32); + self_.height.set(h as u32); + let start = (&self_.start_time).get(); let mut nearst_rounded_time = round_to_nearest(start, minor_tick_step); @@ -120,6 +123,11 @@ impl TimeLine { let d_format = if d.hour() ==0 {d.format("%Y/%m/%d %H:%M").to_string()} else { d.format("%H:%M").to_string()}; let extents = cr.text_extents(&d_format).unwrap(); let x = time_cursor - (extents.width() / 2.0 + extents.x_bearing()); + + if x < margin_horizontal { + continue; + } + cr.move_to(x + margin_horizontal, h / 2.0 + 15.0); cr.show_text(&d_format).unwrap(); } @@ -233,6 +241,11 @@ impl TimeLine { pub fn set_time_start(&self, start_time: DateTime) { self.imp().set_start(start_time); } + pub fn set_selection(&self, selection: Option) { + self.imp().selection.replace(selection); + self.imp().drawing_area.borrow().as_ref().map(|d| d.queue_draw()); + } + pub fn set_border_radius(&self) {} pub fn set_margin_horizontal(&self) {} pub fn set_margin_vertical(&self) {}