diff --git a/hammond-gtk/src/app.rs b/hammond-gtk/src/app.rs index 836fb0c..7627a81 100644 --- a/hammond-gtk/src/app.rs +++ b/hammond-gtk/src/app.rs @@ -36,6 +36,7 @@ pub enum Action { HeaderBarHideUpdateIndicator, MarkAllPlayerNotification(Arc), RemoveShow(Arc), + SetShowWidgetAlignment(Arc), } #[derive(Debug)] @@ -193,6 +194,13 @@ impl App { let notif = remove_show_notif(pd, sender.clone()); notif.show(&overlay); } + Ok(Action::SetShowWidgetAlignment(pd)) => { + content + .get_shows() + .set_widget_scroll_alignment(pd) + .map_err(|err| error!("Failed to set ShowWidget alignment: {}", err)) + .ok(); + } Err(_) => (), } diff --git a/hammond-gtk/src/main.rs b/hammond-gtk/src/main.rs index caa96f3..aa343e9 100644 --- a/hammond-gtk/src/main.rs +++ b/hammond-gtk/src/main.rs @@ -5,7 +5,7 @@ ) )] #![allow(unknown_lints)] -// #![deny(unused_extern_crates, unused)] +#![deny(unused_extern_crates, unused)] extern crate gdk; extern crate gdk_pixbuf; diff --git a/hammond-gtk/src/stacks/show.rs b/hammond-gtk/src/stacks/show.rs index d438402..ace1b04 100644 --- a/hammond-gtk/src/stacks/show.rs +++ b/hammond-gtk/src/stacks/show.rs @@ -3,6 +3,7 @@ use gtk::prelude::*; use gtk::Cast; use failure::Error; +use send_cell::SendCell; use hammond_data::dbqueries; use hammond_data::Podcast; @@ -13,7 +14,7 @@ use app::Action; use widgets::ShowWidget; use std::sync::mpsc::Sender; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; #[derive(Debug, Clone)] pub struct ShowStack { @@ -21,6 +22,11 @@ pub struct ShowStack { sender: Sender, } +lazy_static! { + static ref SHOW_WIDGET_VALIGNMENT: Mutex)>> = + Mutex::new(None); +} + impl ShowStack { pub fn new(sender: Sender) -> Result { let stack = gtk::Stack::new(); @@ -99,31 +105,23 @@ impl ShowStack { .ok_or_else(|| format_err!("Faild to get \"widget\" child from the stack."))? .downcast::() .map_err(|_| format_err!("Failed to downcast stack child to a Box."))?; - debug!("Name: {:?}", WidgetExt::get_name(&old)); + + let oldname = WidgetExt::get_name(&old); + debug!("Name: {:?}", oldname); + oldname + .clone() + .and_then(|id| id.parse().ok()) + .map(|id| save_alignment(id, &old)); let new = ShowWidget::new(pd, self.sender.clone()); // Each composite ShowWidget is a gtkBox with the Podcast.id encoded in the // gtk::Widget name. It's a hack since we can't yet subclass GObject // easily. - let oldid = WidgetExt::get_name(&old); - let newid = WidgetExt::get_name(&new.container); - debug!("Old widget Name: {:?}\nNew widget Name: {:?}", oldid, newid); - - // Only copy the old scrollbar if both widget's represent the same podcast. - if newid == oldid { - let scrolled_window = old.get_children() - .first() - .ok_or_else(|| format_err!("Box container has no childs."))? - .clone() - .downcast::() - .map_err(|_| format_err!("Failed to downcast stack child to a ScrolledWindow."))?; - debug!("Name: {:?}", WidgetExt::get_name(&scrolled_window)); - - // Copy the vertical scrollbar adjustment from the old view into the new one. - scrolled_window - .get_vadjustment() - .map(|x| new.set_vadjustment(&x)); - } + debug!( + "Old widget Name: {:?}\nNew widget Name: {:?}", + oldname, + WidgetExt::get_name(&new.container) + ); self.stack.remove(&old); self.stack.add_named(&new.container, "widget"); @@ -165,6 +163,43 @@ impl ShowStack { self.update_widget() } + pub fn set_widget_scroll_alignment(&self, pd: Arc) -> Result<(), Error> { + let guard = SHOW_WIDGET_VALIGNMENT + .lock() + .map_err(|err| format_err!("Failed to lock widget align mutex: {}", err))?; + + if let Some((oldid, ref sendcell)) = *guard { + // Only copy the old scrollbar if both widget's represent the same podcast. + debug!("PID: {}", pd.id()); + debug!("OLDID: {}", oldid); + if pd.id() != oldid { + debug!("Early return"); + return Ok(()); + }; + + let widget = self.stack + .get_child_by_name("widget") + .ok_or_else(|| format_err!("Faild to get \"widget\" child from the stack."))? + .downcast::() + .map_err(|_| format_err!("Failed to downcast stack child to a Box."))?; + + let scrolled_window = widget + .get_children() + .first() + .ok_or_else(|| format_err!("Box container has no childs."))? + .clone() + .downcast::() + .map_err(|_| format_err!("Failed to downcast stack child to a ScrolledWindow."))?; + + // Copy the vertical scrollbar adjustment from the old view into the new one. + sendcell + .try_get() + .map(|x| scrolled_window.set_vadjustment(&x)); + } + + Ok(()) + } + pub fn switch_podcasts_animated(&self) { self.stack .set_visible_child_full("podcasts", gtk::StackTransitionType::SlideRight); @@ -179,3 +214,24 @@ impl ShowStack { self.stack.clone() } } + +// ATTENTION: EXPECTS THE SHOW WIDGET CONTAINER +fn save_alignment(oldid: i32, widget: >k::Box) -> Result<(), Error> { + let scrolled_window = widget + .get_children() + .first() + .ok_or_else(|| format_err!("Box container has no childs."))? + .clone() + .downcast::() + .map_err(|_| format_err!("Failed to downcast stack child to a ScrolledWindow."))?; + + if let Ok(mut guard) = SHOW_WIDGET_VALIGNMENT.lock() { + let adj = scrolled_window + .get_vadjustment() + .ok_or_else(|| format_err!("Could not get the adjustment"))?; + *guard = Some((oldid, SendCell::new(adj))); + debug!("Widget Alignment was saved with ID: {}.", oldid); + } + + Ok(()) +} diff --git a/hammond-gtk/src/widgets/show.rs b/hammond-gtk/src/widgets/show.rs index 0e78ecf..c7a2eb8 100644 --- a/hammond-gtk/src/widgets/show.rs +++ b/hammond-gtk/src/widgets/show.rs @@ -132,12 +132,12 @@ impl ShowWidget { let count = dbqueries::get_pd_episodes_count(&pd)?; let (sender_, receiver) = bounded(1); - rayon::spawn(move || { + rayon::spawn(clone!(pd => move || { let episodes = dbqueries::get_pd_episodeswidgets(&pd).unwrap(); // The receiver can be dropped if there's an early return // like on show without episodes for example. sender_.send(episodes).ok(); - }); + })); if count == 0 { let builder = gtk::Builder::new_from_resource("/org/gnome/hammond/gtk/empty_show.ui"); @@ -158,7 +158,13 @@ impl ShowWidget { EpisodeWidget::new(ep, sender.clone()).container }); - lazy_load(episodes, list.clone(), constructor, || {}); + let callback = clone!(pd, sender => move || { + sender.send(Action::SetShowWidgetAlignment(pd.clone())) + .map_err(|err| error!("Action Sender: {}", err)) + .ok(); + }); + + lazy_load(episodes, list.clone(), constructor, callback); glib::Continue(false) });