summary refs log tree commit diff
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();