Files
ncspot/src/ui/search.rs
2019-03-20 22:32:45 +01:00

129 lines
3.8 KiB
Rust

#![allow(unused_imports)]
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, ViewRef};
use cursive::{Cursive, Printer, Vec2};
use std::cell::RefCell;
use std::sync::{Arc, Mutex, RwLock};
use queue::Queue;
use spotify::Spotify;
use track::Track;
use ui::listview::ListView;
pub struct SearchView {
results: Arc<RwLock<Vec<Track>>>,
edit: IdView<EditView>,
list: IdView<ListView<Track>>,
edit_focused: bool,
}
impl SearchView {
pub fn new(spotify: Arc<Spotify>, queue: Arc<Queue>) -> SearchView {
let results = Arc::new(RwLock::new(Vec::new()));
let searchfield = EditView::new()
.on_submit(move |s, input| {
if input.len() > 0 {
s.call_on_id("search", |v: &mut SearchView| {
v.run_search(input, spotify.clone());
v.focus_view(&Selector::Id("list")).unwrap();
});
}
})
.with_id("search_edit");
let list = ListView::new(results.clone(), queue).with_id("list");
SearchView {
results: results,
edit: searchfield,
list: list,
edit_focused: true,
}
}
pub fn run_search<S: Into<String>>(&mut self, query: S, spotify: Arc<Spotify>) {
let query = query.into();
let q = query.clone();
self.edit
.call_on(&Selector::Id("search_edit"), |v: &mut EditView| {
v.set_content(q);
});
if let Ok(results) = spotify.search(&query, 50, 0) {
let tracks = results
.tracks
.items
.iter()
.map(|ft| Track::new(ft))
.collect();
let mut r = self.results.write().unwrap();
*r = tracks;
self.edit_focused = false;
}
}
fn pass_event_focused(&mut self, event: Event) -> EventResult {
match self.edit_focused {
true => self.edit.on_event(event),
false => self.list.on_event(event)
}
}
}
impl View for SearchView {
fn draw(&self, printer: &Printer<'_, '_>) {
{
let printer = &printer
.offset((0, 0))
.cropped((printer.size.x, 1))
.focused(self.edit_focused);
self.edit.draw(printer);
}
let printer = &printer
.offset((0, 1))
.cropped((printer.size.x, printer.size.y - 1))
.focused(!self.edit_focused);
self.list.draw(printer);
}
fn layout(&mut self, size: Vec2) {
self.edit.layout(Vec2::new(size.x, 1));
self.list.layout(Vec2::new(size.x, size.y - 1));
}
fn call_on_any<'a>(&mut self, selector: &Selector<'_>, mut callback: AnyCb<'a>) {
self.edit.call_on_any(selector, Box::new(|v| callback(v)));
self.list.call_on_any(selector, Box::new(|v| callback(v)));
}
fn focus_view(&mut self, selector: &Selector<'_>) -> Result<(), ()> {
if let Selector::Id(s) = selector {
self.edit_focused = s == &"search_edit";
Ok(())
} else {
Err(())
}
}
fn on_event(&mut self, event: Event) -> EventResult {
let ret = match event {
Event::Key(Key::Tab) => {
self.edit_focused = !self.edit_focused;
EventResult::Consumed(None)
}
Event::Key(Key::Esc) if self.edit_focused => {
self.edit_focused = false;
EventResult::Consumed(None)
}
_ => self.pass_event_focused(event)
};
ret
}
}