diff --git a/Cargo.toml b/Cargo.toml index bc86c49..8b45a7d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ proj = "0.27.2" image = "0.24.7" anyhow = "1.0.72" proj5 = { version = "0.1.7", features = ["multithreading"] } -relm4 = { version = "0.6.1",features=["libadwaita"]} +relm4 = { version = "0.6.1", features = ["libadwaita"] } relm4-components = "0.6.1" rstar = "*" geo = "0.26.0" @@ -40,11 +40,27 @@ topojson = "0.5.1" geojson = "0.24.1" plotters = "0.3.5" plotters-backend = "0.3.5" -tokio = { version = "1.35.1", features = ["time", "fs", "io-std", "macros", "num_cpus", "bytes", "io-util"] } +tokio = { version = "1.35.1", features = [ + "time", + "fs", + "io-std", + "macros", + "num_cpus", + "bytes", + "io-util", +] } async-trait = "0.1.77" lazy_static = "1.4.0" once_cell = "1.19.0" -relm4-icons = {version="0.6.0",features=["add-filled","delete-filled","chevron-up-filled","chevron-down-filled"]} +relm4-icons = { version = "0.6.0", features = [ + "add-filled", + "delete-filled", + "chevron-up-filled", + "chevron-down-filled", + "play-filled", + "rewind-filled", + "fast-forward-filled", +] } surfman = "0.8.1" euclid = "0.22.9" gl = "0.14.0" @@ -52,7 +68,6 @@ crossbeam = "0.8.4" # plotters-cairo = "0.5.0" - [build-dependencies] glib-build-tools = "0.17.0" [dependencies.geo-macros] @@ -61,4 +76,4 @@ path = "geo-macros" [dependencies.adw] package = "libadwaita" version = "*" -features= ["v1_4"] +features = ["v1_4"] diff --git a/build.rs b/build.rs index 33c8818..ac6db38 100644 --- a/build.rs +++ b/build.rs @@ -1,7 +1,8 @@ fn main() { glib_build_tools::compile_resources( - &["src/resources"], - "src/resources/resources.gresource.xml", - "p.gresource", + &["data"], + // "src/resources/resources.gresource.xml", + "data/css.gresource.xml", + "css.gresource", ); } diff --git a/data/css.gresource.xml b/data/css.gresource.xml new file mode 100644 index 0000000..e525fcf --- /dev/null +++ b/data/css.gresource.xml @@ -0,0 +1,6 @@ + + + + css/main.css + + diff --git a/data/css/main.css b/data/css/main.css new file mode 100644 index 0000000..68d4ae7 --- /dev/null +++ b/data/css/main.css @@ -0,0 +1,30 @@ +.rb { + border-radius: 10px; +} + +paned>separator { + color: transparent; +} + +.h1 { + font-size: 25px; + font-weight: bold; + line-height: 1.25; +} + +.h2 { + font-size: 20px; + font-weight: bold; + line-height: 1.25; +} + +.h3 { + font-size: 15px; + font-weight: bold; + line-height: 1.25; + color: #666; +} + +.content { + font-size: 14px; +} \ No newline at end of file diff --git a/src/components/control_panel/control_panel.rs b/src/components/control_panel/control_panel.rs index a0ff9b7..d0b966b 100644 --- a/src/components/control_panel/control_panel.rs +++ b/src/components/control_panel/control_panel.rs @@ -1,10 +1,10 @@ -use std::path::PathBuf; - -use adw::prelude::WidgetExt; +use crate::timeline::TimeLine; +use adw::prelude::*; use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt, ToggleButtonExt}; use relm4::*; use relm4_components::open_button::{OpenButton, OpenButtonSettings}; use relm4_components::open_dialog::OpenDialogSettings; +use std::path::PathBuf; pub struct ControlPanelModel { open_button: Controller, @@ -34,12 +34,56 @@ impl SimpleComponent for ControlPanelModel { set_orientation: gtk::Orientation::Horizontal, set_spacing: 10, set_size_request: (100, 150), - model.open_button.widget(), - gtk::Button { - set_label: "Edit", + set_margin_horizontal:5, + set_margin_top: 5, + gtk::Frame{ + set_width_request: 100, + gtk::Box{ + set_orientation: gtk::Orientation::Vertical, + set_margin_all:10, + set_spacing: 10, + gtk::Box{ + set_orientation: gtk::Orientation::Vertical, + gtk::Label{ + set_label: "Header", + add_css_class:"h2", + set_halign: gtk::Align::Start, + }, + gtk::Label{ + set_label: "Subheader", + add_css_class:"h3", + set_halign: gtk::Align::Start, + } + }, + #[local] + step_selector -> gtk::DropDown{ + set_expression:None::<>k::Expression>, + connect_selected_notify[sender] => move |step_selector| { + println!("Selected: {}", step_selector.selected()); + }, + }, + gtk::Box{ + set_orientation: gtk::Orientation::Horizontal, + set_spacing:10, + gtk::Button{ + set_icon_name: "rewind-filled" + }, + gtk::Button{ + set_icon_name: "play-filled" + }, + gtk::Button{ + set_icon_name: "fast-forward-filled" + } + } + + } }, - gtk::Button { - set_label: "Export", + gtk::Frame{ + set_width_request: 100, + TimeLine{ + set_hexpand: true, + set_vexpand: true, + } }, } } @@ -58,6 +102,10 @@ impl SimpleComponent for ControlPanelModel { }) .forward(sender.input_sender(), AppMsg::Open); + let select_model = + gtk::StringList::new(&["Option 1", "Option 2", "Option 3", "Editable..."]); + let step_selector = gtk::DropDown::from_strings(&["Option 1", "Option 2", "Option 3"]); + let model = ControlPanelModel { open_button }; let widgets = view_output!(); diff --git a/src/components/monitor/render/render.rs b/src/components/monitor/render/render.rs deleted file mode 100644 index e69de29..0000000 diff --git a/src/components/render_panel/monitor/monitor.rs b/src/components/render_panel/monitor/monitor.rs index 48fa731..2c7055b 100644 --- a/src/components/render_panel/monitor/monitor.rs +++ b/src/components/render_panel/monitor/monitor.rs @@ -66,11 +66,21 @@ impl Component for MonitorModel { set_start_child=>k::Frame{ add_css_class: "rb", set_margin_all: 5, - Render{ - add_css_class: "rb", - #[watch] - set_interior_layers: model.layers.clone(), - } + gtk::Overlay{ + #[wrap(Some)] + set_child = &Render{ + add_css_class: "rb", + #[watch] + set_interior_layers: model.layers.clone(), + }, + add_overlay=>k::Button{ + set_label:"Add", + set_margin_all:10, + set_valign: gtk::Align::Start, + set_halign: gtk::Align::End, + } + }, + }, #[wrap(Some)] set_end_child=model.sidebar.widget(), diff --git a/src/main.rs b/src/main.rs index d17d5f5..dbc7ee4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -16,11 +16,12 @@ mod dynamic_col; mod errors; mod pipeline; mod render; +mod timeline; mod window; use components::app::{AppMode, AppModel}; use once_cell::sync::Lazy; -const APP_ID: &str = "org.gtk_rs.HelloWorld2"; +const APP_ID: &str = "org.tsuki.radar_g"; static RUNTIME: Lazy = Lazy::new(|| Runtime::new().expect("Setting up tokio runtime needs to succeed.")); @@ -51,14 +52,25 @@ fn main() { .unwrap_or(ptr::null()) }); } - - // gio::resources_register_include!("monitor.gresource").expect("Failed to register resources"); - // Create a new application - // let app = Application::builder().application_id(APP_ID).build(); - // // Connect to "activate" signal of `app` - // app.connect_activate(build_ui); - // // Run the application - // app.run() let relm = relm4::RelmApp::new(APP_ID); + initialize_custom_css(); relm.run::(AppMode::Edit); } + +fn initialize_custom_css() { + gio::resources_register_include!("css.gresource").unwrap(); + use gtk::gdk; + // Load the CSS file and add it to the provider + let provider = gtk::CssProvider::new(); + // provider.load_from_string(); + provider.load_from_resource("/org/tsuki/radar_g/css/main.css"); + + use gtk::gdk::Display; + + // Add the provider to the default screen + gtk::style_context_add_provider_for_display( + &Display::default().expect("Could not connect to a display."), + &provider, + gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, + ); +} diff --git a/src/timeline/imp.rs b/src/timeline/imp.rs new file mode 100644 index 0000000..6131d62 --- /dev/null +++ b/src/timeline/imp.rs @@ -0,0 +1,96 @@ +use gtk::cairo; +use gtk::glib::clone; +use gtk::prelude::DrawingAreaExtManual; +use gtk::subclass::prelude::*; +use gtk::traits::{GLAreaExt, WidgetExt}; +use std::cell::RefCell; +use std::num::NonZeroU32; + +use crate::render::Render; + +pub struct TimeLine { + drawing_area: RefCell>, +} + +impl Default for TimeLine { + fn default() -> Self { + Self { + drawing_area: RefCell::new(None), + } + } +} + +#[glib::object_subclass] +impl ObjectSubclass for TimeLine { + const NAME: &'static str = "TimeLine"; + type Type = super::TimeLine; + type ParentType = gtk::Widget; + + fn class_init(klass: &mut Self::Class) { + klass.set_layout_manager_type::(); + } +} + +impl ObjectImpl for TimeLine { + fn constructed(&self) { + let drawing_area = gtk::DrawingArea::new(); + drawing_area.set_draw_func( + (move |_, cr, w, h| { + cr.set_source_rgb(1.0, 0.0, 0.0); + Self::draw_rounded_rectangle(cr, 0f64, 50f64, w as f64, 10f64, 5f64); + cr.fill(); + }), + ); + + let obj = self.obj().clone(); + drawing_area.set_parent(&obj); + drawing_area.set_hexpand(true); + drawing_area.set_vexpand(true); + self.drawing_area.borrow_mut().replace(drawing_area); + self.parent_constructed(); + } +} + +impl WidgetImpl for TimeLine {} + +impl TimeLine { + fn draw_rounded_rectangle( + cr: >k::cairo::Context, + x: f64, + y: f64, + width: f64, + height: f64, + radius: f64, + ) { + cr.new_sub_path(); + cr.arc( + x + width - radius, + y + radius, + radius, + -90f64.to_radians(), + 0f64.to_radians(), + ); + cr.arc( + x + width - radius, + y + height - radius, + radius, + 0f64.to_radians(), + 90f64.to_radians(), + ); + cr.arc( + x + radius, + y + height - radius, + radius, + 90f64.to_radians(), + 180f64.to_radians(), + ); + cr.arc( + x + radius, + y + radius, + radius, + 180f64.to_radians(), + 270f64.to_radians(), + ); + cr.close_path(); + } +} diff --git a/src/timeline/mod.rs b/src/timeline/mod.rs new file mode 100644 index 0000000..86c1527 --- /dev/null +++ b/src/timeline/mod.rs @@ -0,0 +1,23 @@ +mod imp; +pub use glib::subclass::prelude::*; +use glib::{clone, Time}; +use gtk::traits::WidgetExt; +use gtk::{EventControllerScrollFlags, Inhibit}; + +glib::wrapper! { + pub struct TimeLine(ObjectSubclass) + @extends gtk::Widget; +} + +impl Default for TimeLine { + fn default() -> Self { + Self::new() + } +} + +impl TimeLine { + pub fn new() -> Self { + let this: Self = glib::Object::new(); + this + } +}