use crate::cue_view::{CueView, CueViewMsg, CueViewOutput}; use crate::subtitle_selection_dialog::SubtitleSettings; use crate::subtitles::state::CueAddress; use gtk::prelude::*; use relm4::prelude::*; pub struct SubtitleView { primary_cue: Controller, secondary_cue: Option, machine_translation: Option, show_secondary: bool, show_machine_translation: bool, } #[derive(Debug)] pub enum SubtitleViewMsg { SetPrimaryCue(Option), SetSecondaryCue(Option), ApplySubtitleSettings(SubtitleSettings), } #[derive(Debug)] pub enum SubtitleViewOutput { SetHoveringCue(bool), } #[relm4::component(pub)] impl SimpleComponent for SubtitleView { type Init = (); type Input = SubtitleViewMsg; type Output = SubtitleViewOutput; view! { gtk::ScrolledWindow { gtk::Box { set_orientation: gtk::Orientation::Vertical, set_vexpand: true, set_halign: gtk::Align::Center, gtk::Box { set_vexpand: true, }, model.primary_cue.widget(), gtk::Box { #[watch] set_visible: model.show_secondary, set_vexpand: true, }, gtk::Label { #[watch] set_text: model.secondary_cue.as_ref().map(|val| val.as_str()).unwrap_or(""), #[watch] set_visible: model.show_secondary, set_justify: gtk::Justification::Center, }, gtk::Box { #[watch] set_visible: model.show_machine_translation, set_vexpand: true, }, gtk::Label { #[watch] set_text: model.machine_translation.as_ref().map(|val| val.as_str()).unwrap_or(""), #[watch] set_visible: model.show_machine_translation, set_justify: gtk::Justification::Center, }, gtk::Box { set_vexpand: true, }, } }, } fn init( _init: Self::Init, root: Self::Root, sender: ComponentSender, ) -> ComponentParts { let model = Self { primary_cue: CueView::builder() .launch(()) .forward(sender.output_sender(), |output| match output { CueViewOutput::MouseEnter => SubtitleViewOutput::SetHoveringCue(true), CueViewOutput::MouseLeave => SubtitleViewOutput::SetHoveringCue(false), }), secondary_cue: None, machine_translation: None, show_secondary: false, show_machine_translation: false, }; let widgets = view_output!(); ComponentParts { model, widgets } } fn update(&mut self, msg: Self::Input, _sender: ComponentSender) { match msg { SubtitleViewMsg::SetPrimaryCue(addr) => { self.primary_cue .sender() .send(CueViewMsg::SetCue(addr)) .unwrap(); self.machine_translation = addr.and_then(|a| a.resolve_translation()) } SubtitleViewMsg::SetSecondaryCue(addr) => { let text = addr.map(|addr| addr.resolve_text()); self.secondary_cue = text; } SubtitleViewMsg::ApplySubtitleSettings(settings) => { self.show_secondary = settings.show_secondary; self.show_machine_translation = settings.show_machine_translation; } } } }