add calendar and new render_cfg

This commit is contained in:
sleptworld 2024-01-25 01:18:14 +08:00
parent cb68877099
commit 87bb8e6c95
5 changed files with 103 additions and 21 deletions

View File

@ -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<Utc>),
}
#[derive(Debug)]
@ -85,6 +87,8 @@ pub enum AppMsg {
Open(PathBuf),
TimeLine(TimelineMsg),
Selection(Option<DateTime<Utc>>),
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(&gtk::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<ImgItem, gtk::SingleSelection> =
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)));
}
}
}
}
}

View File

@ -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<Layer>,
#[no_eq]
sidebar: Controller<SideBarModel>,
}
@ -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=&gtk::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<Self>,
_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();
}
_ => {}
}

View File

@ -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],
}

View File

@ -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();
}
}

View File

@ -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<Utc>) {
self.imp().set_start(start_time);
}
pub fn set_selection(&self, selection: Option<Selection>) {
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) {}