summaryrefslogtreecommitdiffstats
path: root/src/views/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/views/main.rs')
-rw-r--r--src/views/main.rs192
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)
+ })
+ }
+
+}