Add scroll bar to ListView, remove ScrollView
This commit is contained in:
@@ -367,8 +367,12 @@ impl CommandManager {
|
||||
kb.insert("F3".into(), "playlists".into());
|
||||
kb.insert("F9".into(), "log".into());
|
||||
|
||||
kb.insert("Up".into(), "move up".into());
|
||||
kb.insert("Down".into(), "move down".into());
|
||||
kb.insert("Left".into(), "move left".into());
|
||||
kb.insert("Right".into(), "move right".into());
|
||||
kb.insert("PageUp".into(), "move up 5".into());
|
||||
kb.insert("PageDown".into(), "move down 5".into());
|
||||
kb.insert("k".into(), "move up".into());
|
||||
kb.insert("j".into(), "move down".into());
|
||||
kb.insert("h".into(), "move left".into());
|
||||
|
||||
@@ -2,9 +2,10 @@ use std::cmp::{max, min};
|
||||
use std::sync::{Arc, RwLock};
|
||||
|
||||
use cursive::align::HAlign;
|
||||
use cursive::event::{Event, EventResult, Key};
|
||||
use cursive::event::{Event, EventResult, MouseEvent, MouseButton};
|
||||
use cursive::theme::ColorStyle;
|
||||
use cursive::traits::View;
|
||||
use cursive::view::ScrollBase;
|
||||
use cursive::{Printer, Rect, Vec2};
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
|
||||
@@ -13,7 +14,10 @@ use traits::ListItem;
|
||||
|
||||
pub struct ListView<I: 'static + ListItem> {
|
||||
content: Arc<RwLock<Vec<I>>>,
|
||||
last_content_length: usize,
|
||||
selected: usize,
|
||||
last_size: Vec2,
|
||||
scrollbar: ScrollBase,
|
||||
queue: Arc<Queue>,
|
||||
}
|
||||
|
||||
@@ -21,7 +25,10 @@ impl<I: ListItem> ListView<I> {
|
||||
pub fn new(content: Arc<RwLock<Vec<I>>>, queue: Arc<Queue>) -> Self {
|
||||
Self {
|
||||
content: content,
|
||||
last_content_length: 0,
|
||||
selected: 0,
|
||||
last_size: Vec2::new(0, 0),
|
||||
scrollbar: ScrollBase::new(),
|
||||
queue: queue,
|
||||
}
|
||||
}
|
||||
@@ -37,16 +44,25 @@ impl<I: ListItem> ListView<I> {
|
||||
self.selected
|
||||
}
|
||||
|
||||
pub fn move_focus_to(&mut self, target: usize) {
|
||||
let len = self.content.read().unwrap().len();
|
||||
self.selected = min(target, len - 1);
|
||||
self.scrollbar.scroll_to(self.selected);
|
||||
}
|
||||
|
||||
pub fn move_focus(&mut self, delta: i32) {
|
||||
let len = self.content.read().unwrap().len() as i32;
|
||||
let new = self.selected as i32 + delta;
|
||||
self.selected = min(max(new, 0), len - 1) as usize;
|
||||
self.move_focus_to(max(new, 0) as usize);
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: ListItem> View for ListView<I> {
|
||||
fn draw(&self, printer: &Printer<'_, '_>) {
|
||||
for (i, item) in self.content.read().unwrap().iter().enumerate() {
|
||||
let content = self.content.read().unwrap();
|
||||
|
||||
self.scrollbar.draw(printer, |printer, i| {
|
||||
let item = &content[i];
|
||||
|
||||
let style = if self.selected == i {
|
||||
ColorStyle::highlight()
|
||||
} else if item.is_playing(self.queue.clone()) {
|
||||
@@ -60,7 +76,7 @@ impl<I: ListItem> View for ListView<I> {
|
||||
|
||||
// draw left string
|
||||
printer.with_color(style, |printer| {
|
||||
printer.print((0, i), &left);
|
||||
printer.print((0, 0), &left);
|
||||
});
|
||||
|
||||
// draw ".." to indicate a cut off string
|
||||
@@ -68,7 +84,7 @@ impl<I: ListItem> View for ListView<I> {
|
||||
if max_length < left.width() {
|
||||
let offset = max_length.checked_sub(1).unwrap_or(0);
|
||||
printer.with_color(style, |printer| {
|
||||
printer.print((offset, i), "..");
|
||||
printer.print((offset, 0), "..");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -76,31 +92,64 @@ impl<I: ListItem> View for ListView<I> {
|
||||
let offset = HAlign::Right.get_offset(right.width(), printer.size.x);
|
||||
|
||||
printer.with_color(style, |printer| {
|
||||
printer.print((offset, i), &right);
|
||||
printer.print((offset, 0), &right);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn layout(&mut self, size: Vec2) {
|
||||
self.last_content_length = self.content.read().unwrap().len();
|
||||
self.last_size = size;
|
||||
self.scrollbar.set_heights(size.y, self.last_content_length);
|
||||
}
|
||||
|
||||
fn needs_relayout(&self) -> bool {
|
||||
self.content.read().unwrap().len() != self.last_content_length
|
||||
}
|
||||
|
||||
fn on_event(&mut self, e: Event) -> EventResult {
|
||||
match e {
|
||||
Event::Key(Key::Up) => {
|
||||
self.move_focus(-1);
|
||||
EventResult::Consumed(None)
|
||||
Event::Mouse {
|
||||
event: MouseEvent::WheelUp,
|
||||
..
|
||||
} => {
|
||||
self.move_focus(-3)
|
||||
},
|
||||
Event::Mouse {
|
||||
event: MouseEvent::WheelDown,
|
||||
..
|
||||
} => {
|
||||
self.move_focus(3)
|
||||
},
|
||||
Event::Mouse {
|
||||
event: MouseEvent::Press(MouseButton::Left),
|
||||
position,
|
||||
offset
|
||||
} => if self.scrollbar.scrollable() &&
|
||||
position.y > 0 && position.y <= self.last_size.y &&
|
||||
position.checked_sub(offset)
|
||||
.map(|p| self.scrollbar.start_drag(p, self.last_size.x))
|
||||
.unwrap_or(false)
|
||||
{},
|
||||
Event::Mouse {
|
||||
event: MouseEvent::Hold(MouseButton::Left),
|
||||
position,
|
||||
offset
|
||||
} => if self.scrollbar.scrollable() {
|
||||
self.scrollbar.drag(position.saturating_sub(offset));
|
||||
},
|
||||
Event::Mouse {
|
||||
event: MouseEvent::Release(MouseButton::Left),
|
||||
..
|
||||
} => {
|
||||
self.scrollbar.release_grab();
|
||||
}
|
||||
Event::Key(Key::Down) => {
|
||||
self.move_focus(1);
|
||||
EventResult::Consumed(None)
|
||||
_ => {
|
||||
return EventResult::Ignored;
|
||||
}
|
||||
Event::Key(Key::PageUp) => {
|
||||
self.move_focus(-10);
|
||||
EventResult::Consumed(None)
|
||||
}
|
||||
Event::Key(Key::PageDown) => {
|
||||
self.move_focus(10);
|
||||
EventResult::Consumed(None)
|
||||
}
|
||||
_ => EventResult::Ignored,
|
||||
}
|
||||
|
||||
EventResult::Consumed(None)
|
||||
}
|
||||
|
||||
fn required_size(&mut self, constraint: Vec2) -> Vec2 {
|
||||
|
||||
@@ -2,25 +2,24 @@ use std::sync::Arc;
|
||||
|
||||
use cursive::traits::Identifiable;
|
||||
use cursive::view::ViewWrapper;
|
||||
use cursive::views::{IdView, ScrollView};
|
||||
use cursive::views::IdView;
|
||||
|
||||
use playlists::{Playlist, Playlists};
|
||||
use queue::Queue;
|
||||
use ui::listview::ListView;
|
||||
|
||||
pub struct PlaylistView {
|
||||
list: ScrollView<IdView<ListView<Playlist>>>,
|
||||
list: IdView<ListView<Playlist>>,
|
||||
}
|
||||
|
||||
impl PlaylistView {
|
||||
pub fn new(playlists: &Playlists, queue: Arc<Queue>) -> PlaylistView {
|
||||
let list = ListView::new(playlists.store.clone(), queue).with_id("list");
|
||||
let scrollable = ScrollView::new(list);
|
||||
|
||||
PlaylistView { list: scrollable }
|
||||
PlaylistView { list: list }
|
||||
}
|
||||
}
|
||||
|
||||
impl ViewWrapper for PlaylistView {
|
||||
wrap_impl!(self.list: ScrollView<IdView<ListView<Playlist>>>);
|
||||
wrap_impl!(self.list: IdView<ListView<Playlist>>);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use cursive::traits::Identifiable;
|
||||
use cursive::view::ViewWrapper;
|
||||
use cursive::views::{IdView, ScrollView};
|
||||
use cursive::views::IdView;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -9,18 +9,17 @@ use track::Track;
|
||||
use ui::listview::ListView;
|
||||
|
||||
pub struct QueueView {
|
||||
list: ScrollView<IdView<ListView<Track>>>,
|
||||
list: IdView<ListView<Track>>,
|
||||
}
|
||||
|
||||
impl QueueView {
|
||||
pub fn new(queue: Arc<Queue>) -> QueueView {
|
||||
let list = ListView::new(queue.queue.clone(), queue.clone()).with_id("queue_list");
|
||||
let scrollable = ScrollView::new(list);
|
||||
|
||||
QueueView { list: scrollable }
|
||||
QueueView { list: list }
|
||||
}
|
||||
}
|
||||
|
||||
impl ViewWrapper for QueueView {
|
||||
wrap_impl!(self.list: ScrollView<IdView<ListView<Track>>>);
|
||||
wrap_impl!(self.list: IdView<ListView<Track>>);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ use cursive::direction::Orientation;
|
||||
use cursive::event::{AnyCb, Event, EventResult, Key};
|
||||
use cursive::traits::{Boxable, Finder, Identifiable, View};
|
||||
use cursive::view::{Selector, ViewWrapper};
|
||||
use cursive::views::{EditView, IdView, ScrollView, ViewRef};
|
||||
use cursive::views::{EditView, IdView, ViewRef};
|
||||
use cursive::{Cursive, Printer, Vec2};
|
||||
use std::cell::RefCell;
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
@@ -17,7 +17,7 @@ use ui::listview::ListView;
|
||||
pub struct SearchView {
|
||||
results: Arc<RwLock<Vec<Track>>>,
|
||||
edit: IdView<EditView>,
|
||||
list: ScrollView<IdView<ListView<Track>>>,
|
||||
list: IdView<ListView<Track>>,
|
||||
edit_focused: bool,
|
||||
}
|
||||
|
||||
@@ -36,12 +36,11 @@ impl SearchView {
|
||||
})
|
||||
.with_id("search_edit");
|
||||
let list = ListView::new(results.clone(), queue).with_id("list");
|
||||
let scrollable = ScrollView::new(list);
|
||||
|
||||
SearchView {
|
||||
results: results,
|
||||
edit: searchfield,
|
||||
list: scrollable,
|
||||
list: list,
|
||||
edit_focused: true,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user