Move from ScrollBase to scroll module

`ScrollBase` is deprecated
This commit is contained in:
Henrik Friedrichsen
2022-01-13 21:09:26 +01:00
parent 06c6ea316e
commit adf8da2fc5
3 changed files with 65 additions and 32 deletions

View File

@@ -1,3 +1,4 @@
use cursive::view::scroll::Scroller;
use log::info; use log::info;
use std::cmp::{max, min, Ordering}; use std::cmp::{max, min, Ordering};
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
@@ -6,7 +7,7 @@ use cursive::align::HAlign;
use cursive::event::{Event, EventResult, MouseButton, MouseEvent}; use cursive::event::{Event, EventResult, MouseButton, MouseEvent};
use cursive::theme::{ColorStyle, ColorType, PaletteColor}; use cursive::theme::{ColorStyle, ColorType, PaletteColor};
use cursive::traits::View; use cursive::traits::View;
use cursive::view::ScrollBase; use cursive::view::scroll;
use cursive::{Cursive, Printer, Rect, Vec2}; use cursive::{Cursive, Printer, Rect, Vec2};
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
@@ -38,13 +39,23 @@ pub struct ListView<I: ListItem> {
search_indexes: Vec<usize>, search_indexes: Vec<usize>,
search_selected_index: usize, search_selected_index: usize,
last_size: Vec2, last_size: Vec2,
scrollbar: ScrollBase, scroller: scroll::Core,
queue: Arc<Queue>, queue: Arc<Queue>,
library: Arc<Library>, library: Arc<Library>,
pagination: Pagination<I>, pagination: Pagination<I>,
title: String, title: String,
} }
impl<I: ListItem> Scroller for ListView<I> {
fn get_scroller_mut(&mut self) -> &mut scroll::Core {
&mut self.scroller
}
fn get_scroller(&self) -> &scroll::Core {
&self.scroller
}
}
impl<I: ListItem> ListView<I> { impl<I: ListItem> ListView<I> {
pub fn new(content: Arc<RwLock<Vec<I>>>, queue: Arc<Queue>, library: Arc<Library>) -> Self { pub fn new(content: Arc<RwLock<Vec<I>>>, queue: Arc<Queue>, library: Arc<Library>) -> Self {
Self { Self {
@@ -55,7 +66,7 @@ impl<I: ListItem> ListView<I> {
search_indexes: Vec::new(), search_indexes: Vec::new(),
search_selected_index: 0, search_selected_index: 0,
last_size: Vec2::new(0, 0), last_size: Vec2::new(0, 0),
scrollbar: ScrollBase::new(), scroller: scroll::Core::new(),
queue, queue,
library, library,
pagination: Pagination::default(), pagination: Pagination::default(),
@@ -72,13 +83,22 @@ impl<I: ListItem> ListView<I> {
&self.pagination &self.pagination
} }
fn can_paginate(&self) -> bool { pub fn content_height_with_paginator(&self) -> usize {
if let Some(max) = self.get_pagination().max_content() { let content_len = self.content.read().unwrap().len();
if max > self.last_content_len { log::info!("content len: {content_len}");
return true;
} // add 1 more row for paginator if we can paginate
if self.can_paginate() {
content_len + 1
} else {
content_len
} }
false }
fn can_paginate(&self) -> bool {
let loaded = self.get_pagination().loaded_content();
log::info!("can paginate: {loaded}");
self.get_pagination().max_content().unwrap_or(0) > self.get_pagination().loaded_content()
} }
pub fn get_selected_index(&self) -> usize { pub fn get_selected_index(&self) -> usize {
@@ -102,7 +122,7 @@ impl<I: ListItem> ListView<I> {
pub fn move_focus_to(&mut self, target: usize) { pub fn move_focus_to(&mut self, target: usize) {
let len = self.content.read().unwrap().len().saturating_sub(1); let len = self.content.read().unwrap().len().saturating_sub(1);
self.selected = min(target, len); self.selected = min(target, len);
self.scrollbar.scroll_to(self.selected); self.scroller.scroll_to_y(self.selected);
} }
pub fn move_focus(&mut self, delta: i32) { pub fn move_focus(&mut self, delta: i32) {
@@ -138,7 +158,7 @@ impl<I: ListItem> View for ListView<I> {
fn draw(&self, printer: &Printer<'_, '_>) { fn draw(&self, printer: &Printer<'_, '_>) {
let content = self.content.read().unwrap(); let content = self.content.read().unwrap();
self.scrollbar.draw(printer, |printer, i| { scroll::draw_lines(self, printer, |_, printer, i| {
// draw paginator after content // draw paginator after content
if i == content.len() && self.can_paginate() { if i == content.len() && self.can_paginate() {
let style = ColorStyle::secondary(); let style = ColorStyle::secondary();
@@ -245,25 +265,26 @@ impl<I: ListItem> View for ListView<I> {
} }
fn layout(&mut self, size: Vec2) { fn layout(&mut self, size: Vec2) {
let content_len = self.content.read().unwrap().len();
// add 1 more row for paginator if we can paginate
self.last_content_len = if self.can_paginate() {
content_len + 1
} else {
content_len
};
self.last_size = size; self.last_size = size;
self.scrollbar.set_heights(size.y, self.last_content_len); self.last_content_len = self.content_height_with_paginator();
let relayout_scroller = self.content.read().unwrap().len() != self.last_content_len;
scroll::layout(
self,
size,
relayout_scroller,
|_, _| {},
|s, c| Vec2::new(c.x, s.content_height_with_paginator()),
);
} }
fn needs_relayout(&self) -> bool { fn needs_relayout(&self) -> bool {
self.content.read().unwrap().len() != self.last_content_len self.scroller.needs_relayout()
} }
fn required_size(&mut self, constraint: Vec2) -> Vec2 { fn required_size(&mut self, constraint: Vec2) -> Vec2 {
Vec2::new(constraint.x, self.content.read().unwrap().len()) constraint
} }
fn on_event(&mut self, e: Event) -> EventResult { fn on_event(&mut self, e: Event) -> EventResult {
@@ -281,12 +302,12 @@ impl<I: ListItem> View for ListView<I> {
position, position,
offset, offset,
} => { } => {
if self.scrollbar.scrollable() if self.scroller.get_show_scrollbars()
&& position.y > 0 && position.y > 0
&& position.y <= self.last_size.y && position.y <= self.last_size.y
&& position && position
.checked_sub(offset) .checked_sub(offset)
.map(|p| self.scrollbar.start_drag(p, self.last_size.x)) .map(|p| self.scroller.start_drag(p))
.unwrap_or(false) .unwrap_or(false)
{} {}
} }
@@ -295,15 +316,15 @@ impl<I: ListItem> View for ListView<I> {
position, position,
offset, offset,
} => { } => {
if self.scrollbar.scrollable() { if self.scroller.get_show_scrollbars() {
self.scrollbar.drag(position.saturating_sub(offset)); self.scroller.drag(position.saturating_sub(offset));
} }
} }
Event::Mouse { Event::Mouse {
event: MouseEvent::Release(MouseButton::Left), event: MouseEvent::Release(MouseButton::Left),
.. ..
} => { } => {
self.scrollbar.release_grab(); self.scroller.release_grab();
} }
_ => { _ => {
return EventResult::Ignored; return EventResult::Ignored;

View File

@@ -50,7 +50,9 @@ impl<I: ListItem + Clone> ApiResult<I> {
pub fn apply_pagination(self, pagination: &Pagination<I>) { pub fn apply_pagination(self, pagination: &Pagination<I>) {
let total = self.total as usize; let total = self.total as usize;
let fetched_items = self.items.read().unwrap().len();
pagination.set( pagination.set(
fetched_items,
total, total,
Box::new(move |_| { Box::new(move |_| {
self.next(); self.next();
@@ -79,6 +81,7 @@ impl<I: ListItem + Clone> ApiResult<I> {
pub type Paginator<I> = Box<dyn Fn(Arc<RwLock<Vec<I>>>) + Send + Sync>; pub type Paginator<I> = Box<dyn Fn(Arc<RwLock<Vec<I>>>) + Send + Sync>;
pub struct Pagination<I: ListItem> { pub struct Pagination<I: ListItem> {
loaded_content: Arc<RwLock<usize>>,
max_content: Arc<RwLock<Option<usize>>>, max_content: Arc<RwLock<Option<usize>>>,
callback: Arc<RwLock<Option<Paginator<I>>>>, callback: Arc<RwLock<Option<Paginator<I>>>>,
busy: Arc<RwLock<bool>>, busy: Arc<RwLock<bool>>,
@@ -87,6 +90,7 @@ pub struct Pagination<I: ListItem> {
impl<I: ListItem> Default for Pagination<I> { impl<I: ListItem> Default for Pagination<I> {
fn default() -> Self { fn default() -> Self {
Pagination { Pagination {
loaded_content: Arc::new(RwLock::new(0)),
max_content: Arc::new(RwLock::new(None)), max_content: Arc::new(RwLock::new(None)),
callback: Arc::new(RwLock::new(None)), callback: Arc::new(RwLock::new(None)),
busy: Arc::new(RwLock::new(false)), busy: Arc::new(RwLock::new(false)),
@@ -98,6 +102,7 @@ impl<I: ListItem> Default for Pagination<I> {
impl<I: ListItem> Clone for Pagination<I> { impl<I: ListItem> Clone for Pagination<I> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Pagination { Pagination {
loaded_content: self.loaded_content.clone(),
max_content: self.max_content.clone(), max_content: self.max_content.clone(),
callback: self.callback.clone(), callback: self.callback.clone(),
busy: self.busy.clone(), busy: self.busy.clone(),
@@ -110,11 +115,16 @@ impl<I: ListItem> Pagination<I> {
*self.max_content.write().unwrap() = None; *self.max_content.write().unwrap() = None;
*self.callback.write().unwrap() = None; *self.callback.write().unwrap() = None;
} }
pub fn set(&self, max_content: usize, callback: Paginator<I>) { pub fn set(&self, loaded_content: usize, max_content: usize, callback: Paginator<I>) {
*self.loaded_content.write().unwrap() = loaded_content;
*self.max_content.write().unwrap() = Some(max_content); *self.max_content.write().unwrap() = Some(max_content);
*self.callback.write().unwrap() = Some(callback); *self.callback.write().unwrap() = Some(callback);
} }
pub fn loaded_content(&self) -> usize {
*self.loaded_content.read().unwrap()
}
pub fn max_content(&self) -> Option<usize> { pub fn max_content(&self) -> Option<usize> {
*self.max_content.read().unwrap() *self.max_content.read().unwrap()
} }
@@ -132,7 +142,8 @@ impl<I: ListItem> Pagination<I> {
let cb = pagination.callback.read().unwrap(); let cb = pagination.callback.read().unwrap();
if let Some(ref cb) = *cb { if let Some(ref cb) = *cb {
debug!("calling paginator!"); debug!("calling paginator!");
cb(content); cb(content.clone());
*pagination.loaded_content.write().unwrap() = content.read().unwrap().len();
*pagination.busy.write().unwrap() = false; *pagination.busy.write().unwrap() = false;
library.trigger_redraw(); library.trigger_redraw();
} }

View File

@@ -366,7 +366,8 @@ impl SearchResultsView {
// register paginator if the API has more than one page of results // register paginator if the API has more than one page of results
if let Some(mut paginator) = paginator { if let Some(mut paginator) = paginator {
if total_items > results.read().unwrap().len() { let loaded_items = results.read().unwrap().len();
if total_items > loaded_items {
let ev = ev.clone(); let ev = ev.clone();
// paginator callback // paginator callback
@@ -375,7 +376,7 @@ impl SearchResultsView {
handler(&spotify, &results, &query, offset, true); handler(&spotify, &results, &query, offset, true);
ev.trigger(); ev.trigger();
}; };
paginator.set(total_items, Box::new(cb)); paginator.set(loaded_items, total_items, Box::new(cb));
} else { } else {
paginator.clear() paginator.clear()
} }