use std::ops::Deref; use std::ops::DerefMut; use std::rc::Rc; use anyhow::Result; use cursive::Printer; use cursive::Rect; use cursive::View; use cursive::XY; use cursive::direction::Direction; use cursive::event::Event; use cursive::event::EventResult; use cursive::view::Selector; use cursive::view::ViewNotFound; use crate::runtime::Runtime; use crate::views::maillist::MaillistView; #[derive(Hash, Eq, PartialEq, Clone, parse_display::Display)] pub enum TabPanelName { #[display("Query: {0}")] NotmuchQuery(String), #[display("Other")] Other, } pub struct Tabs(cursive_tabs::TabPanel); impl Deref for Tabs { type Target = cursive_tabs::TabPanel; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for Tabs { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl Tabs { pub fn new(query: &str, rt: Rc) -> Result { let tab_ident = TabPanelName::NotmuchQuery(query.to_string()); let tp = cursive_tabs::TabPanel::new() .with_bar_alignment(cursive_tabs::Align::Start) .with_bar_placement(cursive_tabs::Placement::VerticalLeft) .with_tab(tab_ident, Tab::for_query(rt, query)?); Ok(Tabs(tp)) } pub fn add_tab_for_query(&mut self, rt: Rc, query: &str) -> Result<()> { let ident = TabPanelName::NotmuchQuery(query.to_string()); self.0.add_tab(ident, Tab::for_query(rt, query)?); Ok(()) } } impl View for Tabs { fn draw(&self, printer: &Printer) { self.0.draw(printer); } fn layout(&mut self, xy: XY) { self.0.layout(xy) } fn needs_relayout(&self) -> bool { self.0.needs_relayout() } fn required_size(&mut self, constraint: XY) -> XY { self.0.required_size(constraint) } fn on_event(&mut self, e: Event) -> EventResult { self.0.on_event(e) } fn call_on_any<'a>(&mut self, s: &Selector, tpl: &'a mut (dyn FnMut(&mut (dyn View + 'static)) + 'a)) { self.0.call_on_any(s, tpl); } fn focus_view(&mut self, s: &Selector) -> Result<(), ViewNotFound> { self.0.focus_view(s) } fn take_focus(&mut self, source: Direction) -> bool { self.0.take_focus(source) } fn important_area(&self, view_size: XY) -> Rect { self.0.important_area(view_size) } fn type_name(&self) -> &'static str { self.0.type_name() } } #[derive(getset::Getters, getset::MutGetters)] pub struct Tab { #[getset(get = "pub", get_mut = "pub")] mux: cursive_multiplex::Mux, nodes: Vec, rt: Rc, } impl Tab { fn new(rt: Rc) -> Self { Tab { mux: cursive_multiplex::Mux::new(), nodes: vec![], rt, } } fn for_query(rt: Rc, query: &str) -> Result { use failure::Fail; let mut this = Self::new(rt.clone()); let root = this.mux.root().build().unwrap(); let list = MaillistView::for_query(rt, query)?; this.nodes.push(this.mux.add_right_of(list, root).map_err(|e| e.compat())?); Ok(this) } } impl View for Tab { fn draw(&self, printer: &Printer) { self.mux.draw(printer); } fn layout(&mut self, xy: XY) { self.mux.layout(xy) } fn needs_relayout(&self) -> bool { self.mux.needs_relayout() } fn required_size(&mut self, constraint: XY) -> XY { self.mux.required_size(constraint) } fn on_event(&mut self, e: Event) -> EventResult { self.mux.on_event(e) } fn call_on_any<'a>(&mut self, s: &Selector, tpl: &'a mut (dyn FnMut(&mut (dyn View + 'static)) + 'a)) { self.mux.call_on_any(s, tpl); } fn focus_view(&mut self, s: &Selector) -> Result<(), ViewNotFound> { self.mux.focus_view(s) } fn take_focus(&mut self, source: Direction) -> bool { self.mux.take_focus(source) } fn important_area(&self, view_size: XY) -> Rect { self.mux.important_area(view_size) } fn type_name(&self) -> &'static str { self.mux.type_name() } }