diff options
Diffstat (limited to 'src/views/main.rs')
-rw-r--r-- | src/views/main.rs | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/src/views/main.rs b/src/views/main.rs new file mode 100644 index 0000000..af9dcea --- /dev/null +++ b/src/views/main.rs @@ -0,0 +1,192 @@ +use anyhow::Result; +use cursive::Cursive; +use cursive::Printer; +use cursive::Rect; +use cursive::View; +use cursive::XY; +use cursive::direction::Direction; +use cursive::event::Callback; +use cursive::event::Event; +use cursive::event::EventResult; +use cursive::view::Nameable; +use cursive::view::Selector; +use cursive::views::Dialog; +use cursive::views::EditView; +use cursive::views::NamedView; +use cursive::views::ResizedView; +use cursive::traits::Resizable; +use cursive_multiplex::Mux; +use cursive::view::SizeConstraint; +use cursive::event::Key; +use getset::{Getters, MutGetters}; + +use crate::bindings::BindingCaller; +use crate::bindings::Bindings; +use crate::configuration::Configuration; +use crate::views::mail::MailView; +use crate::views::maillist::MailListingData; +use crate::views::maillist::MaillistView; + +pub const MAIN_VIEW_NAME: &'static str = "main_view"; +pub const MAIN_MUX_NAME: &'static str = "main_mux"; +pub const MAIN_MAIL_LIST_NAME: &'static str = "main_mail_list"; + +#[derive(Getters, MutGetters)] +pub struct MainView { + config: Configuration, + muxroot: cursive_multiplex::Id, + + #[getset(get = "pub", get_mut = "pub")] + tabs: cursive_tabs::TabPanel<String>, + + bindings: Bindings, + bindings_caller: Option<ResizedView<NamedView<BindingCaller>>>, +} + +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<usize>) { + self.tabs.layout(xy) + } + + fn needs_relayout(&self) -> bool { + self.tabs.needs_relayout() + } + + fn required_size(&mut self, constraint: XY<usize>) -> XY<usize> { + 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<(), ()> { + 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<usize>) -> Rect { + self.tabs.important_area(view_size) + } + + fn type_name(&self) -> &'static str { + self.tabs.type_name() + } + +} + +impl MainView { + pub fn new(config: Configuration) -> Result<NamedView<Self>> { + let mut tab = cursive_multiplex::Mux::new(); + let muxroot = tab.root().build().unwrap(); + + { + let dbpath = config.notmuch_database_path(); + let dbquery = config.notmuch_default_query(); + let mlname = MAIN_MAIL_LIST_NAME.to_string(); + let view = MaillistView::create_for(dbpath.to_path_buf(), dbquery, mlname)?; + + let _ = tab.add_right_of(view, muxroot); + } + + let tabs = cursive_tabs::TabPanel::default() + .with_bar_alignment(cursive_tabs::Align::Start) + .with_bar_placement(cursive_tabs::Placement::HorizontalTop) + .with_tab(config.notmuch_default_query().clone(), tab.with_name(MAIN_MUX_NAME)); + + let bindings = crate::bindings::get_bindings(); + + Ok(MainView { config, muxroot, tabs, bindings, bindings_caller: None }.with_name(MAIN_VIEW_NAME)) + } + + pub fn add_tab<T: View>(&mut self, id: String, view: T) { + self.tabs.add_tab(id, view) + } + + pub fn config(&self) -> &Configuration { + &self.config + } + + pub fn add_notmuch_query_layer(siv: &mut Cursive) { + use crate::util::dialog_for; + use crate::util::error_dialog_for; + + let edit_view = EditView::new() + .on_submit(move |siv: &mut Cursive, query: &str| { + siv.call_on_name(MAIN_VIEW_NAME, move |main_view: &mut MainView| { + main_view.config().notmuch_database_path().clone() + }) + .map(|dbpath| { + let t = MaillistView::create_for(dbpath.to_path_buf(), query, query.to_string())? + .full_screen() + .with_name(format!("{}-view", query)); + + siv.call_on_name(MAIN_VIEW_NAME, move |main_view: &mut MainView| { + main_view.add_tab(query.to_string(), t); + }); + + siv.pop_layer(); + Ok(()) + }) + .unwrap_or_else(|| { + siv.pop_layer(); + siv.add_layer(dialog_for("Failed to get database connection set up")); + Ok(()) + }) + .unwrap_or_else(|e: anyhow::Error| { + siv.pop_layer(); + siv.add_layer(error_dialog_for(e)) + }); + }) + .with_name("query"); + + siv.add_layer({ + Dialog::around(edit_view) + .title("Query") + .min_width(80) + }) + } + +} |