timeline scroll
This commit is contained in:
parent
7a1b9adb61
commit
cb68877099
61
Cargo.lock
generated
61
Cargo.lock
generated
@ -1075,9 +1075,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
|
checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@ -1090,9 +1090,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
|
checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
@ -1100,15 +1100,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-core"
|
name = "futures-core"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
|
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-executor"
|
name = "futures-executor"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
|
checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-task",
|
"futures-task",
|
||||||
@ -1117,15 +1117,15 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-io"
|
name = "futures-io"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
|
checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-macro"
|
name = "futures-macro"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
|
checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.76",
|
"proc-macro2 1.0.76",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
@ -1134,21 +1134,21 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-sink"
|
name = "futures-sink"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
|
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-task"
|
name = "futures-task"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
|
checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-util"
|
name = "futures-util"
|
||||||
version = "0.3.28"
|
version = "0.3.30"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
|
checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@ -2960,9 +2960,9 @@ checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "relm4"
|
name = "relm4"
|
||||||
version = "0.6.1"
|
version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "813306b9bc23e2f1e719801eb9aa59e4c2f96830be951a6168ad0c53363c6196"
|
checksum = "0c16f3fad883034773b7f5af4d7e865532b8f3641e5a8bab2a34561a8d960d81"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"flume",
|
"flume",
|
||||||
@ -2978,9 +2978,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "relm4-components"
|
name = "relm4-components"
|
||||||
version = "0.6.1"
|
version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "edd02dd4c31b952cedb6f3ef200438963b1c4b7889f2ce760c607a1dc7f513e3"
|
checksum = "5485d72dc94c12a59c571d80cf9a545e5b9a2f0ebc90ea5fd234929a9376f66d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"relm4",
|
"relm4",
|
||||||
@ -2999,9 +2999,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "relm4-macros"
|
name = "relm4-macros"
|
||||||
version = "0.6.1"
|
version = "0.6.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ad8d946cf33654b1df3e2e7d1c4952a154f008368cdda03a99c1840a6fcab3b"
|
checksum = "9340e2553c0a184a80a0bfa1dcf73c47f3d48933aa6be90724b202f9fbd24735"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.76",
|
"proc-macro2 1.0.76",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
@ -3591,11 +3591,10 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.37"
|
version = "0.1.40"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
|
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tracing-attributes",
|
"tracing-attributes",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
@ -3603,9 +3602,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-attributes"
|
name = "tracing-attributes"
|
||||||
version = "0.1.26"
|
version = "0.1.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
|
checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.76",
|
"proc-macro2 1.0.76",
|
||||||
"quote 1.0.35",
|
"quote 1.0.35",
|
||||||
@ -3614,9 +3613,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing-core"
|
name = "tracing-core"
|
||||||
version = "0.1.31"
|
version = "0.1.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
|
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::timeline::TimeLine;
|
use crate::timeline::TimeLine;
|
||||||
use adw::prelude::*;
|
use adw::prelude::*;
|
||||||
use chrono::{DateTime, Duration, Utc};
|
use chrono::{prelude::*, DateTime, Duration, TimeZone, Utc};
|
||||||
use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt, ToggleButtonExt};
|
use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt, ToggleButtonExt};
|
||||||
use relm4::typed_list_view::{RelmListItem, TypedListView};
|
use relm4::typed_list_view::{RelmListItem, TypedListView};
|
||||||
use relm4::*;
|
use relm4::*;
|
||||||
@ -12,6 +12,7 @@ use std::path::PathBuf;
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ControlPanelModel {
|
pub struct ControlPanelModel {
|
||||||
timeline_start: DateTime<Utc>,
|
timeline_start: DateTime<Utc>,
|
||||||
|
selection: Option<DateTime<Utc>>,
|
||||||
#[tracker::no_eq]
|
#[tracker::no_eq]
|
||||||
open_button: Controller<OpenButton>,
|
open_button: Controller<OpenButton>,
|
||||||
#[tracker::no_eq]
|
#[tracker::no_eq]
|
||||||
@ -83,6 +84,7 @@ pub enum TimelineMsg {
|
|||||||
pub enum AppMsg {
|
pub enum AppMsg {
|
||||||
Open(PathBuf),
|
Open(PathBuf),
|
||||||
TimeLine(TimelineMsg),
|
TimeLine(TimelineMsg),
|
||||||
|
Selection(Option<DateTime<Utc>>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[relm4::component(pub)]
|
#[relm4::component(pub)]
|
||||||
@ -168,6 +170,17 @@ impl SimpleComponent for ControlPanelModel {
|
|||||||
set_width_request: 400,
|
set_width_request: 400,
|
||||||
#[track = "model.changed(ControlPanelModel::timeline_start())"]
|
#[track = "model.changed(ControlPanelModel::timeline_start())"]
|
||||||
set_time_start: model.timeline_start,
|
set_time_start: model.timeline_start,
|
||||||
|
connect_start_time_notify[sender] => move |time| {
|
||||||
|
let time = time.start_time();
|
||||||
|
sender.input(
|
||||||
|
AppMsg::Selection(
|
||||||
|
if time > i64::MIN {
|
||||||
|
Some(Utc.timestamp_opt(time, 0).unwrap())
|
||||||
|
} else{
|
||||||
|
None
|
||||||
|
}));
|
||||||
|
|
||||||
|
},
|
||||||
},
|
},
|
||||||
gtk::Button{
|
gtk::Button{
|
||||||
set_icon_name: "fast-forward-filled",
|
set_icon_name: "fast-forward-filled",
|
||||||
@ -178,6 +191,7 @@ impl SimpleComponent for ControlPanelModel {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
gtk::ScrolledWindow{
|
gtk::ScrolledWindow{
|
||||||
set_height_request: 75,
|
set_height_request: 75,
|
||||||
#[local_ref]
|
#[local_ref]
|
||||||
@ -188,6 +202,9 @@ impl SimpleComponent for ControlPanelModel {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
gtk::Separator{
|
||||||
|
set_orientation: gtk::Orientation::Vertical,
|
||||||
|
},
|
||||||
gtk::ScrolledWindow{
|
gtk::ScrolledWindow{
|
||||||
set_hexpand: true,
|
set_hexpand: true,
|
||||||
gtk::Box{
|
gtk::Box{
|
||||||
@ -228,6 +245,7 @@ impl SimpleComponent for ControlPanelModel {
|
|||||||
let timeline_start = Utc::now();
|
let timeline_start = Utc::now();
|
||||||
|
|
||||||
let model = ControlPanelModel {
|
let model = ControlPanelModel {
|
||||||
|
selection: None,
|
||||||
timeline_start,
|
timeline_start,
|
||||||
open_button,
|
open_button,
|
||||||
list_img_wrapper,
|
list_img_wrapper,
|
||||||
@ -249,6 +267,9 @@ impl SimpleComponent for ControlPanelModel {
|
|||||||
self.set_timeline_start(current + c);
|
self.set_timeline_start(current + c);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
AppMsg::Selection(selection) => {
|
||||||
|
self.set_selection(selection);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/main.rs
10
src/main.rs
@ -1,12 +1,7 @@
|
|||||||
mod utils;
|
mod utils;
|
||||||
use gtk::prelude::*;
|
use gtk::gio;
|
||||||
use gtk::{gio, glib, Application, ApplicationWindow};
|
|
||||||
use pipeline::offscreen_renderer::OffscreenRenderer;
|
|
||||||
use relm4::menu;
|
|
||||||
use relm4::RelmApp;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use tokio::runtime::Runtime;
|
use tokio::runtime::Runtime;
|
||||||
use utils::creator;
|
|
||||||
mod chart;
|
mod chart;
|
||||||
mod components;
|
mod components;
|
||||||
mod coords;
|
mod coords;
|
||||||
@ -59,14 +54,11 @@ fn main() {
|
|||||||
|
|
||||||
fn initialize_custom_css() {
|
fn initialize_custom_css() {
|
||||||
gio::resources_register_include!("css.gresource").unwrap();
|
gio::resources_register_include!("css.gresource").unwrap();
|
||||||
use gtk::gdk;
|
|
||||||
// Load the CSS file and add it to the provider
|
// Load the CSS file and add it to the provider
|
||||||
let provider = gtk::CssProvider::new();
|
let provider = gtk::CssProvider::new();
|
||||||
// provider.load_from_string();
|
// provider.load_from_string();
|
||||||
provider.load_from_resource("/org/tsuki/radar_g/css/main.css");
|
provider.load_from_resource("/org/tsuki/radar_g/css/main.css");
|
||||||
|
|
||||||
use gtk::gdk::Display;
|
use gtk::gdk::Display;
|
||||||
|
|
||||||
// Add the provider to the default screen
|
// Add the provider to the default screen
|
||||||
gtk::style_context_add_provider_for_display(
|
gtk::style_context_add_provider_for_display(
|
||||||
&Display::default().expect("Could not connect to a display."),
|
&Display::default().expect("Could not connect to a display."),
|
||||||
|
|||||||
@ -7,7 +7,6 @@ mod renders;
|
|||||||
pub use self::cms::CMS;
|
pub use self::cms::CMS;
|
||||||
pub use self::imp::{RenderConfig, RenderMotion, RenderStatus};
|
pub use self::imp::{RenderConfig, RenderMotion, RenderStatus};
|
||||||
use crate::coords::Mapper;
|
use crate::coords::Mapper;
|
||||||
use crate::RUNTIME;
|
|
||||||
use adw::prelude::{GLAreaExt, GestureDragExt};
|
use adw::prelude::{GLAreaExt, GestureDragExt};
|
||||||
use geo_types::LineString;
|
use geo_types::LineString;
|
||||||
use glib::clone;
|
use glib::clone;
|
||||||
@ -15,10 +14,7 @@ pub use glib::subclass::prelude::*;
|
|||||||
use gtk::traits::WidgetExt;
|
use gtk::traits::WidgetExt;
|
||||||
use gtk::{EventControllerScrollFlags, Inhibit};
|
use gtk::{EventControllerScrollFlags, Inhibit};
|
||||||
pub use interior::*;
|
pub use interior::*;
|
||||||
use relm4::once_cell::sync::Lazy;
|
use std::cell::{Ref, RefMut};
|
||||||
use std::cell::{Ref, RefCell, RefMut};
|
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use tokio::runtime::Runtime;
|
|
||||||
|
|
||||||
pub(super) type WindowCoord = (f32, f32);
|
pub(super) type WindowCoord = (f32, f32);
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use chrono::{prelude::*, Duration};
|
use chrono::{prelude::*, Duration};
|
||||||
use glib::Properties;
|
use gtk::glib::{self, prelude::*, ParamSpec, Properties, Property, Value};
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
use gtk::subclass::prelude::*;
|
use gtk::subclass::prelude::*;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
@ -11,8 +11,8 @@ pub enum Selection {
|
|||||||
Point(DateTime<Utc>),
|
Point(DateTime<Utc>),
|
||||||
}
|
}
|
||||||
|
|
||||||
// #[derive(Properties)]
|
#[derive(Properties)]
|
||||||
// #[properties(wrapper_type = super::TimeLine)]
|
#[properties(wrapper_type = super::TimeLine)]
|
||||||
pub struct TimeLine {
|
pub struct TimeLine {
|
||||||
pub(super) drawing_area: RefCell<Option<gtk::DrawingArea>>,
|
pub(super) drawing_area: RefCell<Option<gtk::DrawingArea>>,
|
||||||
pub(super) height: Cell<u32>,
|
pub(super) height: Cell<u32>,
|
||||||
@ -26,6 +26,11 @@ pub struct TimeLine {
|
|||||||
pub(super) border_radius: Cell<f64>,
|
pub(super) border_radius: Cell<f64>,
|
||||||
pub(super) tick_selection: Rc<Cell<usize>>,
|
pub(super) tick_selection: Rc<Cell<usize>>,
|
||||||
pub(super) start_time: Cell<DateTime<Utc>>,
|
pub(super) start_time: Cell<DateTime<Utc>>,
|
||||||
|
#[property(name = "start-time", get, set)]
|
||||||
|
pub(super) start_time_stamp: Cell<i64>,
|
||||||
|
#[property(name = "end-time", get, set)]
|
||||||
|
pub(super) end_time_stamp: Cell<i64>,
|
||||||
|
pub(super) dpi: Cell<f64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for TimeLine {
|
impl Default for TimeLine {
|
||||||
@ -43,6 +48,9 @@ impl Default for TimeLine {
|
|||||||
border_radius: Cell::new(8.0),
|
border_radius: Cell::new(8.0),
|
||||||
tick_selection: Rc::new(Cell::new(0)),
|
tick_selection: Rc::new(Cell::new(0)),
|
||||||
start_time: Cell::new(Utc::now()),
|
start_time: Cell::new(Utc::now()),
|
||||||
|
start_time_stamp: Cell::new(i64::MIN),
|
||||||
|
end_time_stamp: Cell::new(i64::MIN),
|
||||||
|
dpi: Cell::new(3600f64/30.0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -58,7 +66,43 @@ impl ObjectSubclass for TimeLine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ObjectImpl for TimeLine {}
|
impl ObjectImpl for TimeLine {
|
||||||
|
fn properties() -> &'static [ParamSpec] {
|
||||||
|
Self::derived_properties()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_property(&self, id: usize, value: &Value, pspec: &ParamSpec) {
|
||||||
|
match pspec.name() {
|
||||||
|
"start-time" => {
|
||||||
|
self.selection.set(Some(Selection::Point(
|
||||||
|
Utc.timestamp_opt(value.get().unwrap(), 0).unwrap(),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
"end-time" => {
|
||||||
|
self.end_time_stamp.set(value.get().unwrap());
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
self.derived_set_property(id, value, pspec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn property(&self, id: usize, pspec: &ParamSpec) -> Value {
|
||||||
|
match pspec.name() {
|
||||||
|
"start-time" => match self.selection.get() {
|
||||||
|
Some(Selection::Slice((start, _))) => start.timestamp().to_value(),
|
||||||
|
Some(Selection::Point(time)) => time.timestamp().to_value(),
|
||||||
|
None => self.start_time_stamp.get().to_value(),
|
||||||
|
},
|
||||||
|
"end-time" => match self.selection.get() {
|
||||||
|
Some(Selection::Slice((_, end))) => end.timestamp().to_value(),
|
||||||
|
Some(Selection::Point(time)) => time.timestamp().to_value(),
|
||||||
|
None => self.start_time_stamp.get().to_value(),
|
||||||
|
},
|
||||||
|
_ => self.derived_property(id, pspec),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl WidgetImpl for TimeLine {}
|
impl WidgetImpl for TimeLine {}
|
||||||
|
|
||||||
@ -137,3 +181,12 @@ pub(super) fn draw_cursor(cr: >k::cairo::Context, x: f64, y: f64, width: f64,
|
|||||||
// 绘制三角形部分
|
// 绘制三角形部分
|
||||||
cr.fill().expect("Failed to fill the triangle");
|
cr.fill().expect("Failed to fill the triangle");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TimeLine {
|
||||||
|
fn get_selection_stamp(&self) -> Option<i64> {
|
||||||
|
self.selection.get().map(|selection| match selection {
|
||||||
|
Selection::Slice((start, _)) => start.timestamp(),
|
||||||
|
Selection::Point(time) => time.timestamp(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -7,6 +7,8 @@ use gtk::traits::WidgetExt;
|
|||||||
use gtk::EventControllerMotion;
|
use gtk::EventControllerMotion;
|
||||||
pub use imp::Selection;
|
pub use imp::Selection;
|
||||||
use imp::{draw_cursor, draw_rounded_rectangle, round_to_nearest};
|
use imp::{draw_cursor, draw_rounded_rectangle, round_to_nearest};
|
||||||
|
use std::cell::Cell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
glib::wrapper! {
|
glib::wrapper! {
|
||||||
pub struct TimeLine(ObjectSubclass<imp::TimeLine>)
|
pub struct TimeLine(ObjectSubclass<imp::TimeLine>)
|
||||||
@ -115,7 +117,7 @@ impl TimeLine {
|
|||||||
let d = Utc.timestamp_opt(time_stamp, 0).unwrap();
|
let d = Utc.timestamp_opt(time_stamp, 0).unwrap();
|
||||||
|
|
||||||
if d.hour() % 3 == 0 {
|
if d.hour() % 3 == 0 {
|
||||||
let d_format = d.format("%H:%M").to_string();
|
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 extents = cr.text_extents(&d_format).unwrap();
|
||||||
let x = time_cursor - (extents.width() / 2.0 + extents.x_bearing());
|
let x = time_cursor - (extents.width() / 2.0 + extents.x_bearing());
|
||||||
cr.move_to(x + margin_horizontal, h / 2.0 + 15.0);
|
cr.move_to(x + margin_horizontal, h / 2.0 + 15.0);
|
||||||
@ -164,34 +166,61 @@ impl TimeLine {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let gesture_click = gtk::GestureClick::new();
|
let gesture_click = gtk::GestureClick::new();
|
||||||
|
let click_position = Rc::new(Cell::new(0f64));
|
||||||
gesture_click.set_button(1);
|
gesture_click.set_button(1);
|
||||||
gesture_click.connect_pressed(clone!(@weak drawing_area, @weak this =>move |gesture, _, x, y| {
|
gesture_click.connect_pressed(clone!(@strong click_position => move |_, _, x, _| {
|
||||||
let self_ = this.imp();
|
click_position.set(x);
|
||||||
let mut gesture_click_selection = self_.selection.clone();
|
}));
|
||||||
|
|
||||||
|
gesture_click.connect_released(
|
||||||
|
clone!(@strong click_position,@weak drawing_area, @weak this =>move |_, _, x, _| {
|
||||||
|
if click_position.get() != x {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let self_ = this.imp();
|
||||||
let margin_horizontal = self_.margin_horizontal.get() as f64;
|
let margin_horizontal = self_.margin_horizontal.get() as f64;
|
||||||
let major_tick_step = self_.major_tick_step.get();
|
let major_tick_step = self_.major_tick_step.get();
|
||||||
let minor_tick_step = self_.minor_tick_step.get();
|
|
||||||
let major_tick_interval = self_.major_tick_interval.get() as f64;
|
let major_tick_interval = self_.major_tick_interval.get() as f64;
|
||||||
let minor_tick_interval = major_tick_interval / (major_tick_step / minor_tick_step) as f64;
|
|
||||||
let height = self_.height.get();
|
|
||||||
let width = self_.width.get();
|
let width = self_.width.get();
|
||||||
|
|
||||||
let start = (&self_.start_time).get();
|
let start = (&self_.start_time).get();
|
||||||
let x = x.clamp(margin_horizontal, width as f64 - margin_horizontal);
|
let x = x.clamp(margin_horizontal, width as f64 - margin_horizontal);
|
||||||
let secs = (x - margin_horizontal) / (major_tick_interval / major_tick_step as f64);
|
let secs = (x - margin_horizontal) / (major_tick_interval / major_tick_step as f64);
|
||||||
|
|
||||||
gesture_click_selection.replace(Some(Selection::Point(
|
let selection_start = start + Duration::seconds(secs as i64);
|
||||||
start + Duration::seconds(secs as i64),
|
|
||||||
)));
|
|
||||||
|
|
||||||
|
self_.selection.set(Some(Selection::Point(
|
||||||
|
selection_start
|
||||||
|
)));
|
||||||
|
this.set_start_time(selection_start.timestamp());
|
||||||
cursor_pos_clicker_clone.replace(None);
|
cursor_pos_clicker_clone.replace(None);
|
||||||
drawing_area.queue_draw();
|
drawing_area.queue_draw();
|
||||||
|
|
||||||
}));
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
let temp_start = Rc::new(Cell::new(self_.start_time.get()));
|
||||||
|
let drag_detecture = gtk::GestureDrag::new();
|
||||||
|
drag_detecture.connect_drag_update(
|
||||||
|
clone!(@strong temp_start,@weak this as canvas => move |this, _, _| {
|
||||||
|
let self_ = canvas.imp();
|
||||||
|
let dpi = self_.dpi.get();
|
||||||
|
let (ox, _) = this.offset().unwrap_or((0.0,0.0));
|
||||||
|
|
||||||
|
canvas.set_time_start(temp_start.get() - Duration::seconds((ox * dpi) as i64));
|
||||||
|
canvas.imp().drawing_area.borrow().as_ref().map(|d| d.queue_draw());
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
drag_detecture.connect_drag_end(clone!(
|
||||||
|
@strong temp_start,@weak this => move |_,_,_|{
|
||||||
|
temp_start.set(this.imp().start_time.get());
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
drawing_area.add_controller(gesture_click);
|
drawing_area.add_controller(gesture_click);
|
||||||
drawing_area.add_controller(motion_controller);
|
drawing_area.add_controller(motion_controller);
|
||||||
|
drawing_area.add_controller(drag_detecture);
|
||||||
drawing_area.set_hexpand(true);
|
drawing_area.set_hexpand(true);
|
||||||
drawing_area.set_vexpand(true);
|
drawing_area.set_vexpand(true);
|
||||||
drawing_area.set_parent(&this);
|
drawing_area.set_parent(&this);
|
||||||
|
|||||||
12
src/utils.rs
12
src/utils.rs
@ -1,11 +1,13 @@
|
|||||||
|
use chrono::{DateTime, Utc};
|
||||||
|
use gtk::glib::{HasParamSpec, ParamSpecInt64, ParamSpecInt64Builder, ToValue};
|
||||||
use std::{borrow::BorrowMut, num::NonZeroU32};
|
use std::{borrow::BorrowMut, num::NonZeroU32};
|
||||||
|
|
||||||
use euclid::Size2D;
|
use euclid::Size2D;
|
||||||
use femtovg::Canvas;
|
use femtovg::Canvas;
|
||||||
use ndarray::{Array2, ArrayView1};
|
use ndarray::{Array2, ArrayView1};
|
||||||
use surfman::{
|
use surfman::{
|
||||||
Connection, Context, ContextAttributeFlags, ContextAttributes, ContextDescriptor,
|
Connection, Context, ContextAttributeFlags, ContextAttributes, ContextDescriptor, Device,
|
||||||
NativeConnection, NativeContext, SurfaceAccess, SurfaceType, Device, GLVersion,
|
GLVersion, NativeConnection, NativeContext, SurfaceAccess, SurfaceType,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn meshgrid<T>(x: ArrayView1<T>, y: ArrayView1<T>) -> (Array2<T>, Array2<T>)
|
pub fn meshgrid<T>(x: ArrayView1<T>, y: ArrayView1<T>) -> (Array2<T>, Array2<T>)
|
||||||
@ -24,10 +26,12 @@ pub fn creator() {
|
|||||||
let adapter = connection.create_adapter().unwrap();
|
let adapter = connection.create_adapter().unwrap();
|
||||||
let mut device = connection.create_device(&adapter).unwrap();
|
let mut device = connection.create_device(&adapter).unwrap();
|
||||||
let api = device.gl_api();
|
let api = device.gl_api();
|
||||||
let descriptor = device.create_context_descriptor(&ContextAttributes {
|
let descriptor = device
|
||||||
|
.create_context_descriptor(&ContextAttributes {
|
||||||
version: GLVersion::new(3, 3),
|
version: GLVersion::new(3, 3),
|
||||||
flags: ContextAttributeFlags::empty(),
|
flags: ContextAttributeFlags::empty(),
|
||||||
}).unwrap();
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let mut context = device.create_context(&descriptor, None).unwrap();
|
let mut context = device.create_context(&descriptor, None).unwrap();
|
||||||
let mut surface = device
|
let mut surface = device
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user