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::event::Key; use cursive::traits::Resizable; use cursive::view::Nameable; use cursive::view::Selector; use cursive::view::SizeConstraint; use cursive::view::ViewNotFound; use cursive::views::NamedView; use cursive::views::ResizedView; use getset::{Getters, MutGetters}; use crate::bindings::BindingCaller; use crate::bindings::Bindings; use crate::tabs::*; use crate::runtime::Runtime; pub const MAIN_VIEW_NAME: &'static str = "main_view"; #[derive(Getters, MutGetters)] pub struct MainView { rt: Rc, #[getset(get = "pub", get_mut = "pub")] tabs: crate::tabs::Tabs, bindings: Bindings, bindings_caller: Option>>, } impl MainView { pub fn new(rt: Rc) -> Result> { let default_query = rt.config().notmuch_default_query(); let tabs = Tabs::new(default_query, rt.clone())?; let bindings = crate::bindings::get_bindings(); Ok(MainView { rt, tabs, bindings, bindings_caller: None }.with_name(MAIN_VIEW_NAME)) } pub fn get_current_tab(&self) -> Option<&cursive_multiplex::Mux> { if let Some(mux) = self.tabs.get_active_tab() { mux.downcast_ref::() } else { None } } pub fn get_current_mux(&self) -> Option<&Box> { if let Some(mux) = self.get_current_tab() { return mux.get_current_view() } None } pub fn get_current_tab_mut(&mut self) -> Option<&mut cursive_multiplex::Mux> { if let Some(mux) = self.tabs.get_active_tab_mut() { mux.downcast_mut::() } else { None } } pub fn get_current_mux_mut(&mut self) -> Option<&mut Box> { if let Some(mut mux) = self.get_current_tab_mut() { return mux.get_current_view_mut() } None } } impl View for MainView { fn draw(&self, printer: &Printer) { self.tabs.draw(printer); if let Some(caller) = self.bindings_caller.as_ref() { caller.draw(printer); } } fn layout(&mut self, xy: XY) { self.tabs.layout(xy) } fn needs_relayout(&self) -> bool { self.tabs.needs_relayout() } fn required_size(&mut self, constraint: XY) -> XY { self.tabs.required_size(constraint) } fn on_event(&mut self, e: Event) -> EventResult { debug!("Received event: {:?}", e); match self.bindings_caller.as_mut() { Some(caller) => match e { Event::Key(Key::Esc) => { self.bindings_caller = None; debug!("Escape. Resetting bindings caller."); EventResult::Consumed(None) }, other => { debug!("Forwarding event to bindings caller"); caller.on_event(other) }, }, None => match e { Event::Char(':') => { debug!(": -> Constructing bindings caller."); self.bindings_caller = Some({ self.bindings.caller() .with_name(crate::bindings::BINDINGS_CALLER) .resized(SizeConstraint::Full, SizeConstraint::AtLeast(5)) }); EventResult::Consumed(None) }, other => { debug!("Forwarding event to tabs"); self.tabs.on_event(other) }, } } } fn call_on_any<'a>(&mut self, s: &Selector, tpl: &'a mut (dyn FnMut(&mut (dyn View + 'static)) + 'a)) { self.tabs.call_on_any(s, tpl); } fn focus_view(&mut self, s: &Selector) -> Result<(), ViewNotFound> { self.tabs.focus_view(s) } fn take_focus(&mut self, source: Direction) -> bool { self.tabs.take_focus(source) } fn important_area(&self, view_size: XY) -> Rect { self.tabs.important_area(view_size) } fn type_name(&self) -> &'static str { self.tabs.type_name() } }