diff --git a/hammond-gtk/src/stacks/populated.rs b/hammond-gtk/src/stacks/populated.rs index 2052ea1..90776ce 100644 --- a/hammond-gtk/src/stacks/populated.rs +++ b/hammond-gtk/src/stacks/populated.rs @@ -60,20 +60,30 @@ impl PopulatedStack { } pub fn update_shows(&mut self) -> Result<(), Error> { + // The current visible child might change depending on + // removal and insertion in the gtk::Stack, so we have + // to make sure it will stay the same. + let s = self.state; + self.replace_shows()?; + self.switch_visible(s, gtk::StackTransitionType::None); + + Ok(()) + } + + pub fn replace_shows(&mut self) -> Result<(), Error> { let old = &self.populated.container.clone(); debug!("Name: {:?}", WidgetExt::get_name(old)); + self.populated + .save_alignment() + .map_err(|err| error!("Failed to set episodes_view allignment: {}", err)) + .ok(); + let pop = ShowsView::new(self.sender.clone())?; self.populated = pop; self.stack.remove(old); self.stack.add_named(&self.populated.container, "shows"); - // The current visible child might change depending on - // removal and insertion in the gtk::Stack, so we have - // to make sure it will stay the same. - let s = self.state; - self.switch_visible(s, gtk::StackTransitionType::None); - old.destroy(); Ok(()) } diff --git a/hammond-gtk/src/widgets/shows_view.rs b/hammond-gtk/src/widgets/shows_view.rs index 78d395a..56e9492 100644 --- a/hammond-gtk/src/widgets/shows_view.rs +++ b/hammond-gtk/src/widgets/shows_view.rs @@ -1,16 +1,23 @@ -use failure::Error; use gtk; use gtk::prelude::*; +use failure::Error; +use send_cell::SendCell; + use hammond_data::dbqueries; use hammond_data::Podcast; use app::Action; -use utils::{get_ignored_shows, lazy_load, set_image_from_path}; +use utils::{self, get_ignored_shows, lazy_load, set_image_from_path}; use std::rc::Rc; use std::sync::mpsc::Sender; use std::sync::Arc; +use std::sync::Mutex; + +lazy_static! { + static ref SHOWS_VIEW_VALIGNMENT: Mutex>> = Mutex::new(None); +} #[derive(Debug, Clone)] pub struct ShowsView { @@ -37,33 +44,69 @@ impl Default for ShowsView { impl ShowsView { pub fn new(sender: Sender) -> Result, Error> { let pop = Rc::new(ShowsView::default()); - pop.init(sender)?; + pop.init(sender); + // Populate the flowbox with the Podcasts. + populate_flowbox(&pop)?; Ok(pop) } - pub fn init(&self, sender: Sender) -> Result<(), Error> { + pub fn init(&self, sender: Sender) { self.flowbox.connect_child_activated(move |_, child| { on_child_activate(child, &sender) .map_err(|err| error!("Error along flowbox child activation: {}", err)) .ok(); }); - // Populate the flowbox with the Podcasts. - self.populate_flowbox() } - fn populate_flowbox(&self) -> Result<(), Error> { - let ignore = get_ignored_shows()?; - let podcasts = dbqueries::get_podcasts_filter(&ignore)?; + /// Set scrolled window vertical adjustment. + #[allow(unused)] + fn set_vadjustment(&self) -> Result<(), Error> { + let guard = SHOWS_VIEW_VALIGNMENT + .lock() + .map_err(|err| format_err!("Failed to lock widget align mutex: {}", err))?; - let flowbox = self.flowbox.clone(); - let constructor = |parent| ShowsChild::new(&parent).child; - let callback = move || flowbox.show_all(); - - let flowbox = self.flowbox.clone(); - lazy_load(podcasts, flowbox, constructor, callback); + if let Some(ref sendcell) = *guard { + // Copy the vertical scrollbar adjustment from the old view into the new one. + sendcell + .try_get() + .map(|x| utils::smooth_scroll_to(&self.scrolled_window, &x)); + } Ok(()) } + + /// Save the vertical scrollbar position. + pub fn save_alignment(&self) -> Result<(), Error> { + if let Ok(mut guard) = SHOWS_VIEW_VALIGNMENT.lock() { + let adj = self.scrolled_window + .get_vadjustment() + .ok_or_else(|| format_err!("Could not get the adjustment"))?; + *guard = Some(SendCell::new(adj)); + info!("Saved episodes_view alignment."); + } + + Ok(()) + } +} + +fn populate_flowbox(shows: &Rc) -> Result<(), Error> { + let ignore = get_ignored_shows()?; + let podcasts = dbqueries::get_podcasts_filter(&ignore)?; + + let flowbox = shows.flowbox.clone(); + let constructor = clone!(flowbox => move |parent| { + flowbox.show_all(); + ShowsChild::new(&parent).child + }); + + let callback = clone!(shows => move || { + shows.set_vadjustment() + .map_err(|err| error!("Failed to set ShowsView Alignment: {}", err)) + .ok(); + }); + + lazy_load(podcasts, flowbox, constructor, callback); + Ok(()) } fn on_child_activate(child: >k::FlowBoxChild, sender: &Sender) -> Result<(), Error> {