aboutsummaryrefslogtreecommitdiff
path: root/src/cue_view.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/cue_view.rs')
-rw-r--r--src/cue_view.rs81
1 files changed, 55 insertions, 26 deletions
diff --git a/src/cue_view.rs b/src/cue_view.rs
index fbf2520..05c45c4 100644
--- a/src/cue_view.rs
+++ b/src/cue_view.rs
@@ -8,18 +8,25 @@ use relm4::prelude::*;
use relm4::{ComponentParts, SimpleComponent};
use unicode_segmentation::UnicodeSegmentation;
+use crate::subtitles::state::CueAddress;
+use crate::translation::TRANSLATIONS;
use crate::util::Tracker;
-pub struct CueView {
- text: Tracker<Option<String>>,
+pub struct ActiveCueViewState {
+ addr: CueAddress,
+ text: String,
// byte ranges for the words in `text`
word_ranges: Vec<Range<usize>>,
}
+pub struct CueView {
+ state: Tracker<Option<ActiveCueViewState>>,
+}
+
#[derive(Debug)]
pub enum CueViewMsg {
// messages from the app
- SetText(Option<String>),
+ SetCue(Option<CueAddress>),
// messages from UI
MouseMotion,
}
@@ -42,7 +49,7 @@ impl SimpleComponent for CueView {
gtk::Label {
add_controller: event_controller.clone(),
set_use_markup: true,
- set_visible: false,
+ set_sensitive: false,
set_justify: gtk::Justification::Center,
add_css_class: "cue-view",
},
@@ -71,8 +78,7 @@ impl SimpleComponent for CueView {
sender: relm4::ComponentSender<Self>,
) -> relm4::ComponentParts<Self> {
let model = Self {
- text: Tracker::new(None),
- word_ranges: Vec::new(),
+ state: Tracker::new(None),
};
let widgets = view_output!();
@@ -81,19 +87,26 @@ impl SimpleComponent for CueView {
}
fn update(&mut self, message: Self::Input, _sender: relm4::ComponentSender<Self>) {
- match message {
- CueViewMsg::SetText(text) => {
- self.text.set(text);
+ self.state.reset();
- if let Some(text) = self.text.get() {
- self.word_ranges = UnicodeSegmentation::unicode_word_indices(text.as_str())
+ match message {
+ CueViewMsg::SetCue(addr) => {
+ if let Some(addr) = addr {
+ let text = addr.resolve_text();
+ let word_ranges = UnicodeSegmentation::unicode_word_indices(text.as_str())
.map(|(offset, slice)| Range {
start: offset,
end: offset + slice.len(),
})
.collect();
+
+ self.state.set(Some(ActiveCueViewState {
+ addr,
+ text,
+ word_ranges,
+ }))
} else {
- self.word_ranges = Vec::new();
+ self.state.set(None);
}
}
CueViewMsg::MouseMotion => {
@@ -103,11 +116,16 @@ impl SimpleComponent for CueView {
}
fn post_view() {
- if self.text.is_dirty() {
- if let Some(text) = self.text.get() {
+ if self.state.is_dirty() {
+ if let Some(ActiveCueViewState {
+ addr: _,
+ text,
+ word_ranges,
+ }) = self.state.get()
+ {
let mut markup = String::new();
- let mut it = self.word_ranges.iter().enumerate().peekable();
+ let mut it = word_ranges.iter().enumerate().peekable();
if let Some((_, first_word_range)) = it.peek() {
markup.push_str(
glib::markup_escape_text(&text[..first_word_range.start]).as_str(),
@@ -127,24 +145,35 @@ impl SimpleComponent for CueView {
markup.push_str(glib::markup_escape_text(&text[next_gap_range]).as_str());
}
- widgets.label.set_markup(markup.as_str());
- widgets.label.set_visible(true);
+ widgets.label.set_markup(&markup);
+ widgets.label.set_sensitive(true);
} else {
- widgets.label.set_visible(false);
+ // insensitive = invisible by css
+ widgets.label.set_sensitive(false);
}
}
- if let Some(word_ix_str) = widgets.label.current_uri() {
- let range = self
- .word_ranges
- .get(usize::from_str(word_ix_str.as_str()).unwrap())
- .unwrap();
- widgets
- .popover_label
- .set_text(&self.text.get().as_ref().unwrap()[range.clone()]);
+ if let (
+ Some(ActiveCueViewState {
+ addr: CueAddress(stream_ix, cue_ix),
+ text: _,
+ word_ranges,
+ }),
+ Some(word_ix_str),
+ ) = (self.state.get(), widgets.label.current_uri())
+ {
+ let word_ix = usize::from_str(word_ix_str.as_str()).unwrap();
+
+ {
+ // TODO get translation
+ widgets.popover_label.set_text(word_ix_str.as_str());
+ }
+
+ let range = word_ranges.get(word_ix).unwrap();
widgets
.popover
.set_pointing_to(Some(&Self::get_rect_of_byte_range(&widgets.label, &range)));
+
widgets.popover.popup();
} else {
widgets.popover.popdown();