mxl_player_components/ui/video_offsets_dialog/
widget.rs1use crate::localization::helper::fl;
2use crate::ui::video_offsets_dialog::messages::{
3 VideoOffsetsComponentInput, VideoOffsetsComponentOutput, internal::PrivateMsg,
4};
5use crate::ui::video_offsets_dialog::model::{VideoOffsetsComponentInit, VideoOffsetsComponentModel};
6use mxl_relm4_components::relm4::{self, adw::prelude::*, prelude::*};
7
8const CONVERSION_RATE: f64 = 1000000_f64;
9const OFFSET_MIN: f64 = -1500_f64;
10const OFFSET_MAX: f64 = 1500_f64;
11const OFFSET_INCREMENT_STEP: f64 = 1_f64;
12const OFFSET_PAGE_INCREMENT: f64 = 100_f64;
13const OFFSET_PAGE_SIZE: f64 = 0_f64;
14
15#[relm4::component(pub)]
16impl Component for VideoOffsetsComponentModel {
17 type Init = VideoOffsetsComponentInit;
18 type Input = VideoOffsetsComponentInput;
19 type Output = VideoOffsetsComponentOutput;
20 type CommandOutput = ();
21
22 view! {
23 adw::PreferencesWindow {
24 set_title: Some(&fl!("video-offsets")),
25 set_hide_on_close: true,
26 set_destroy_with_parent: true,
27
28 add = &adw::PreferencesPage {
29 set_vexpand: true,
30
31 add = &adw::PreferencesGroup {
32 adw::ActionRow {
33 set_hexpand: true,
34 set_title: &fl!("video-offsets-audio"),
35 set_subtitle: &fl!("video-offsets-audio", "description"),
36
37 add_suffix = >k::SpinButton {
38 set_halign: gtk::Align::End,
39 set_valign: gtk::Align::Center,
40 #[watch]
41 #[block_signal(audio_video_offset_changed_handler)]
42 set_adjustment: >k::Adjustment::new(model.audio_video_offset as f64 / CONVERSION_RATE,
43 OFFSET_MIN,
44 OFFSET_MAX,
45 OFFSET_INCREMENT_STEP,
46 OFFSET_PAGE_INCREMENT,
47 OFFSET_PAGE_SIZE),
48 connect_value_changed[sender] => move |spin_button| {
49 sender
50 .input_sender()
51 .send(VideoOffsetsComponentInput::PrivateMessage(
52 PrivateMsg::AudioVideoOffsetChanged((spin_button.value() * CONVERSION_RATE) as i64),
53 ))
54 .unwrap_or_default();
55 } @audio_video_offset_changed_handler,
56 },
57 },
58
59 adw::ActionRow {
60 set_hexpand: true,
61 set_title: &fl!("video-offsets-subtitle"),
62 set_subtitle: &fl!("video-offsets-subtitle", "description"),
63
64 add_suffix = >k::SpinButton {
65 set_halign: gtk::Align::End,
66 set_valign: gtk::Align::Center,
67 #[watch]
68 #[block_signal(subtitle_video_offset_changed_handler)]
69 set_adjustment: >k::Adjustment::new(model.subtitle_video_offset as f64 / CONVERSION_RATE,
70 OFFSET_MIN,
71 OFFSET_MAX,
72 OFFSET_INCREMENT_STEP,
73 OFFSET_PAGE_INCREMENT,
74 OFFSET_PAGE_SIZE),
75 connect_value_changed[sender] => move |spin_button| {
76 sender
77 .input_sender()
78 .send(VideoOffsetsComponentInput::PrivateMessage(
79 PrivateMsg::SubtitleVideoOffsetChanged((spin_button.value() * CONVERSION_RATE) as i64),
80 ))
81 .unwrap_or_default();
82 } @subtitle_video_offset_changed_handler,
83 },
84 },
85 },
86 }
87 }
88 }
89
90 fn init(init: Self::Init, root: Self::Root, sender: ComponentSender<Self>) -> ComponentParts<Self> {
92 let model = VideoOffsetsComponentModel {
93 audio_video_offset: init.audio_video_offset,
94 subtitle_video_offset: init.subtitle_video_offset,
95 };
96
97 let widgets = view_output!();
98
99 ComponentParts { model, widgets }
100 }
101
102 fn update_with_view(
103 &mut self,
104 widgets: &mut Self::Widgets,
105 msg: Self::Input,
106 sender: ComponentSender<Self>,
107 _: &Self::Root,
108 ) {
109 match msg {
110 VideoOffsetsComponentInput::SetAudioVideoOffset(offset) => self.audio_video_offset = offset,
111 VideoOffsetsComponentInput::SetSubtitleVideoOffset(offset) => self.subtitle_video_offset = offset,
112 VideoOffsetsComponentInput::PrivateMessage(msg) => match msg {
113 PrivateMsg::AudioVideoOffsetChanged(offset) => {
114 sender
115 .output(VideoOffsetsComponentOutput::SetAudioVideoOffset(offset))
116 .unwrap_or_default();
117 }
118 PrivateMsg::SubtitleVideoOffsetChanged(offset) => {
119 sender
120 .output(VideoOffsetsComponentOutput::SetSubtitleVideoOffset(offset))
121 .unwrap_or_default();
122 }
123 },
124 }
125 self.update_view(widgets, sender)
126 }
127}
128
129impl VideoOffsetsComponentModel {
130 pub fn audio_video_offset(&self) -> i64 {
131 self.audio_video_offset
132 }
133
134 pub fn subtitle_video_offset(&self) -> i64 {
135 self.subtitle_video_offset
136 }
137}