h-gtk: Animate the adjustment of scrolled windows.
Many thanks to Julian Spaber for documenting this.
This commit is contained in:
parent
b0ac037964
commit
8951a6e237
@ -1,5 +1,6 @@
|
||||
#![cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
|
||||
|
||||
use gdk::FrameClockExt;
|
||||
use gdk_pixbuf::Pixbuf;
|
||||
use glib;
|
||||
use gtk;
|
||||
@ -101,6 +102,40 @@ where
|
||||
});
|
||||
}
|
||||
|
||||
// Kudos to Julian Sparber
|
||||
// https://blogs.gnome.org/jsparber/2018/04/29/animate-a-scrolledwindow/
|
||||
pub fn smooth_scroll_to(view: gtk::ScrolledWindow, target: gtk::Adjustment) {
|
||||
if let Some(adj) = view.get_vadjustment() {
|
||||
if let Some(clock) = view.get_frame_clock() {
|
||||
let duration = 200;
|
||||
let start = adj.get_value();
|
||||
let end = target.get_value();
|
||||
let start_time = clock.get_frame_time();
|
||||
let end_time = start_time + 1000 * duration;
|
||||
|
||||
view.add_tick_callback(move |_, clock| {
|
||||
let now = clock.get_frame_time();
|
||||
if now < end_time && adj.get_value() != end {
|
||||
let mut t = (now - start_time) as f64 / (end_time - start_time) as f64;
|
||||
t = ease_out_cubic(t);
|
||||
adj.set_value(start + t * (end - start));
|
||||
return glib::Continue(true);
|
||||
} else {
|
||||
adj.set_value(end);
|
||||
return glib::Continue(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// From clutter-easing.c, based on Robert Penner's
|
||||
// infamous easing equations, MIT license.
|
||||
fn ease_out_cubic(t: f64) -> f64 {
|
||||
let p = t - 1f64;
|
||||
return p * p * p + 1f64;
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref IGNORESHOWS: Arc<Mutex<HashSet<i32>>> = Arc::new(Mutex::new(HashSet::new()));
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
use chrono::prelude::*;
|
||||
use failure::Error;
|
||||
|
||||
use gtk;
|
||||
use gtk::prelude::*;
|
||||
|
||||
@ -8,8 +9,7 @@ use hammond_data::EpisodeWidgetQuery;
|
||||
use send_cell::SendCell;
|
||||
|
||||
use app::Action;
|
||||
use utils::lazy_load_full;
|
||||
use utils::{get_ignored_shows, set_image_from_path};
|
||||
use utils::{self, lazy_load_full};
|
||||
use widgets::EpisodeWidget;
|
||||
|
||||
use std::rc::Rc;
|
||||
@ -90,7 +90,7 @@ impl HomeView {
|
||||
use self::ListSplit::*;
|
||||
|
||||
let view = Rc::new(HomeView::default());
|
||||
let ignore = get_ignored_shows()?;
|
||||
let ignore = utils::get_ignored_shows()?;
|
||||
let episodes = dbqueries::get_episodes_widgets_filter_limit(&ignore, 100)?;
|
||||
let now_utc = Utc::now();
|
||||
|
||||
@ -132,7 +132,7 @@ impl HomeView {
|
||||
// Copy the vertical scrollbar adjustment from the old view into the new one.
|
||||
sendcell
|
||||
.try_get()
|
||||
.map(|x| self.scrolled_window.set_vadjustment(&x));
|
||||
.map(|x| utils::smooth_scroll_to(self.scrolled_window.clone(), x.clone()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -231,6 +231,6 @@ impl EpisodesViewWidget {
|
||||
|
||||
#[inline]
|
||||
fn set_cover(&self, podcast_id: i32) -> Result<(), Error> {
|
||||
set_image_from_path(&self.image, podcast_id, 64)
|
||||
utils::set_image_from_path(&self.image, podcast_id, 64)
|
||||
}
|
||||
}
|
||||
|
||||
@ -165,7 +165,7 @@ impl ShowWidget {
|
||||
// Copy the vertical scrollbar adjustment from the old view into the new one.
|
||||
sendcell
|
||||
.try_get()
|
||||
.map(|x| self.scrolled_window.set_vadjustment(&x));
|
||||
.map(|x| utils::smooth_scroll_to(self.scrolled_window.clone(), x.clone()));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
Loading…
Reference in New Issue
Block a user