ShowWidget: Try to retain scrollbar adjustment.
This commit is contained in:
parent
b8995d838a
commit
54641fc3c5
@ -36,6 +36,7 @@ pub enum Action {
|
||||
HeaderBarHideUpdateIndicator,
|
||||
MarkAllPlayerNotification(Arc<Podcast>),
|
||||
RemoveShow(Arc<Podcast>),
|
||||
SetShowWidgetAlignment(Arc<Podcast>),
|
||||
}
|
||||
|
||||
#[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(_) => (),
|
||||
}
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
)
|
||||
)]
|
||||
#![allow(unknown_lints)]
|
||||
// #![deny(unused_extern_crates, unused)]
|
||||
#![deny(unused_extern_crates, unused)]
|
||||
|
||||
extern crate gdk;
|
||||
extern crate gdk_pixbuf;
|
||||
|
||||
@ -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<Action>,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref SHOW_WIDGET_VALIGNMENT: Mutex<Option<(i32, SendCell<gtk::Adjustment>)>> =
|
||||
Mutex::new(None);
|
||||
}
|
||||
|
||||
impl ShowStack {
|
||||
pub fn new(sender: Sender<Action>) -> Result<ShowStack, Error> {
|
||||
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::<gtk::Box>()
|
||||
.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::<gtk::ScrolledWindow>()
|
||||
.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<Podcast>) -> 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::<gtk::Box>()
|
||||
.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::<gtk::ScrolledWindow>()
|
||||
.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::<gtk::ScrolledWindow>()
|
||||
.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(())
|
||||
}
|
||||
|
||||
@ -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)
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user