use crate::timeline::TimeLine; use adw::prelude::*; use gtk::prelude::{BoxExt, ButtonExt, GtkWindowExt, OrientableExt, ToggleButtonExt}; use relm4::typed_list_view::{RelmListItem, TypedListView}; use relm4::*; use relm4_components::open_button::{OpenButton, OpenButtonSettings}; use relm4_components::open_dialog::OpenDialogSettings; use std::path::PathBuf; use chrono::{DateTime, Utc, Duration}; pub struct ControlPanelModel { open_button: Controller, list_img_wrapper: TypedListView, } #[derive(Debug, PartialEq, PartialOrd, Ord, Eq)] struct ImgItem { time: String, img: Option, visiable: bool, } impl ImgItem { fn new(time: String, img: Option, visiable: bool) -> Self { Self { time, img, visiable, } } } struct Widgets { img: gtk::Image, } impl RelmListItem for ImgItem { type Root = gtk::Frame; type Widgets = Widgets; fn setup(_item: >k::ListItem) -> (gtk::Frame, Widgets) { relm4::view! { my_box = gtk::Frame { set_height_request: 70, set_width_request: 100, gtk::Box{ set_margin_all:2, #[name = "img"] gtk::Image{} } } } let widgets = Widgets { img }; (my_box, widgets) } fn bind(&mut self, widgets: &mut Self::Widgets, _root: &mut Self::Root) { let Widgets { img } = widgets; } } #[derive(Debug)] pub enum HeaderOutput { View, Edit, Export, } #[derive(Debug)] pub enum AppMsg { Open(PathBuf), } #[relm4::component(pub)] impl SimpleComponent for ControlPanelModel { type Init = i8; type Output = HeaderOutput; type Input = AppMsg; view! { #[root] gtk::Box { set_orientation: gtk::Orientation::Horizontal, set_spacing: 10, set_size_request: (100, 150), 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::Frame{ gtk::Box{ set_orientation:gtk::Orientation::Vertical, set_margin_horizontal:10, set_margin_vertical:10, set_spacing: 4, gtk::Label{ set_label: "TimeLine", add_css_class:"h2", set_halign: gtk::Align::Start, }, gtk::Box{ TimeLine{ set_height_request: 40, set_width_request: 381, set_time_start: Utc::now(), set_selection: Some(crate::timeline::Selection::Point( Utc::now() + Duration::hours(1) )), } }, gtk::ScrolledWindow{ set_height_request: 75, #[local_ref] my_view -> gtk::ListView{ add_css_class: "lv", set_orientation: gtk::Orientation::Horizontal, } }, } }, }, gtk::ScrolledWindow{ set_vexpand: true, } } fn init( init: Self::Init, root: &Self::Root, sender: relm4::ComponentSender, ) -> relm4::ComponentParts { let open_button = OpenButton::builder() .launch(OpenButtonSettings { dialog_settings: OpenDialogSettings::default(), text: "Open file", recently_opened_files: Some(".recent_files"), max_recent_files: 10, }) .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 mut list_img_wrapper: TypedListView = TypedListView::with_sorting(); list_img_wrapper.append(ImgItem::new("00:00:00".to_string(), None, true)); let model = ControlPanelModel { open_button, list_img_wrapper, }; let my_view = &model.list_img_wrapper.view; let widgets = view_output!(); ComponentParts { model, widgets } } fn update(&mut self, msg: Self::Input, _sender: ComponentSender) { match msg { AppMsg::Open(p) => println!("Open file: {:?}", p), } } }