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))]
|
#![cfg_attr(feature = "cargo-clippy", allow(type_complexity))]
|
||||||
|
|
||||||
|
use gdk::FrameClockExt;
|
||||||
use gdk_pixbuf::Pixbuf;
|
use gdk_pixbuf::Pixbuf;
|
||||||
use glib;
|
use glib;
|
||||||
use gtk;
|
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! {
|
lazy_static! {
|
||||||
static ref IGNORESHOWS: Arc<Mutex<HashSet<i32>>> = Arc::new(Mutex::new(HashSet::new()));
|
static ref IGNORESHOWS: Arc<Mutex<HashSet<i32>>> = Arc::new(Mutex::new(HashSet::new()));
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
use chrono::prelude::*;
|
use chrono::prelude::*;
|
||||||
use failure::Error;
|
use failure::Error;
|
||||||
|
|
||||||
use gtk;
|
use gtk;
|
||||||
use gtk::prelude::*;
|
use gtk::prelude::*;
|
||||||
|
|
||||||
@ -8,8 +9,7 @@ use hammond_data::EpisodeWidgetQuery;
|
|||||||
use send_cell::SendCell;
|
use send_cell::SendCell;
|
||||||
|
|
||||||
use app::Action;
|
use app::Action;
|
||||||
use utils::lazy_load_full;
|
use utils::{self, lazy_load_full};
|
||||||
use utils::{get_ignored_shows, set_image_from_path};
|
|
||||||
use widgets::EpisodeWidget;
|
use widgets::EpisodeWidget;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -90,7 +90,7 @@ impl HomeView {
|
|||||||
use self::ListSplit::*;
|
use self::ListSplit::*;
|
||||||
|
|
||||||
let view = Rc::new(HomeView::default());
|
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 episodes = dbqueries::get_episodes_widgets_filter_limit(&ignore, 100)?;
|
||||||
let now_utc = Utc::now();
|
let now_utc = Utc::now();
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ impl HomeView {
|
|||||||
// Copy the vertical scrollbar adjustment from the old view into the new one.
|
// Copy the vertical scrollbar adjustment from the old view into the new one.
|
||||||
sendcell
|
sendcell
|
||||||
.try_get()
|
.try_get()
|
||||||
.map(|x| self.scrolled_window.set_vadjustment(&x));
|
.map(|x| utils::smooth_scroll_to(self.scrolled_window.clone(), x.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -231,6 +231,6 @@ impl EpisodesViewWidget {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn set_cover(&self, podcast_id: i32) -> Result<(), Error> {
|
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.
|
// Copy the vertical scrollbar adjustment from the old view into the new one.
|
||||||
sendcell
|
sendcell
|
||||||
.try_get()
|
.try_get()
|
||||||
.map(|x| self.scrolled_window.set_vadjustment(&x));
|
.map(|x| utils::smooth_scroll_to(self.scrolled_window.clone(), x.clone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user