diff options
author | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2019-03-02 19:25:11 +0200 |
---|---|---|
committer | Manos Pitsidianakis <el13635@mail.ntua.gr> | 2019-06-10 19:40:38 +0300 |
commit | d285913974b418bde8fa94688d59522aae68dc66 (patch) | |
tree | 1107d7c411add0bfc4a8a173296cf33964630ea6 /ui | |
parent | 12cc9950c72b41b73c79160cc0f09617c01c644a (diff) |
Add shortcut panel
Concerns #63
Diffstat (limited to 'ui')
-rw-r--r-- | ui/src/components.rs | 5 | ||||
-rw-r--r-- | ui/src/components/mail/listing.rs | 8 | ||||
-rw-r--r-- | ui/src/components/mail/listing/compact.rs | 17 | ||||
-rw-r--r-- | ui/src/components/utilities.rs | 57 | ||||
-rw-r--r-- | ui/src/types/keys.rs | 2 |
5 files changed, 88 insertions, 1 deletions
diff --git a/ui/src/components.rs b/ui/src/components.rs index 6fbe2ddb..594ac8f9 100644 --- a/ui/src/components.rs +++ b/ui/src/components.rs @@ -45,6 +45,7 @@ use std::fmt; use std::fmt::{Debug, Display}; use std::ops::{Deref, DerefMut}; +use fnv::FnvHashMap; use uuid::Uuid; use super::{Key, StatusEvent, UIEvent, UIEventType}; @@ -141,6 +142,8 @@ impl Entity { } } +pub type ShortcutMap = FnvHashMap<Key, String>; + /// Types implementing this Trait can draw on the terminal and receive events. /// If a type wants to skip drawing if it has not changed anything, it can hold some flag in its /// fields (eg self.dirty = false) and act upon that in their `draw` implementation. @@ -153,6 +156,8 @@ pub trait Component: Display + Debug + Send { fn set_dirty(&mut self); fn kill(&mut self, _id: EntityId) {} fn set_id(&mut self, _id: EntityId) {} + + fn get_shortcuts(&self) -> ShortcutMap { Default::default() } } /* diff --git a/ui/src/components/mail/listing.rs b/ui/src/components/mail/listing.rs index 15381b2c..07f7347f 100644 --- a/ui/src/components/mail/listing.rs +++ b/ui/src/components/mail/listing.rs @@ -115,6 +115,14 @@ impl Component for Listing { Listing::Threaded(l) => l.set_dirty(), } } + + fn get_shortcuts(&self) -> ShortcutMap { + match self { + Listing::Compact(l) => l.get_shortcuts(), + Listing::Plain(l) => l.get_shortcuts(), + Listing::Threaded(l) => l.get_shortcuts(), + } + } } impl From<IndexStyle> for Listing { diff --git a/ui/src/components/mail/listing/compact.rs b/ui/src/components/mail/listing/compact.rs index f1b5f6c7..e39f27d6 100644 --- a/ui/src/components/mail/listing/compact.rs +++ b/ui/src/components/mail/listing/compact.rs @@ -523,4 +523,21 @@ impl Component for CompactListing { } self.dirty = true; } + + fn get_shortcuts(&self) -> ShortcutMap { + let mut map = self.view.as_ref().map(|p| p.get_shortcuts()).unwrap_or(ShortcutMap::default()); + + map.insert(Key::Char('\n'), "Open thread.".into()); + map.insert(Key::PageUp, "Go to previous page.".into()); + map.insert(Key::PageDown, "Go to next page.".into()); + map.insert(Key::Char('i'), "Exit thread view.".into()); + map.insert(Key::Char('J'), "Go to previous folder.".into()); + map.insert(Key::Char('K'), "Go to next folder.".into()); + map.insert(Key::Char('h'), "Go to previous account.".into()); + map.insert(Key::Char('l'), "Go to next account.".into()); + map.insert(Key::Char('m'), "Start new mail draft in new tab.".into()); + + map + } + } diff --git a/ui/src/components/utilities.rs b/ui/src/components/utilities.rs index 801dfa76..cde01e22 100644 --- a/ui/src/components/utilities.rs +++ b/ui/src/components/utilities.rs @@ -91,13 +91,21 @@ impl Component for HSplit { fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { self.top.rcv_event(event, context) || self.bottom.rcv_event(event, context) } + fn is_dirty(&self) -> bool { self.top.component.is_dirty() || self.bottom.component.is_dirty() } + fn set_dirty(&mut self) { self.top.component.set_dirty(); self.bottom.component.set_dirty(); } + + fn get_shortcuts(&self) -> ShortcutMap { + let mut top_map = self.top.get_shortcuts(); + top_map.extend(self.bottom.get_shortcuts().into_iter()); + top_map + } } /// A vertically split in half container. @@ -175,16 +183,25 @@ impl Component for VSplit { .component .draw(grid, ((mid + 1, get_y(upper_left)), bottom_right), context); } + fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { (self.left.rcv_event(event, context) || self.right.rcv_event(event, context)) } + fn is_dirty(&self) -> bool { self.left.component.is_dirty() || self.right.component.is_dirty() } + fn set_dirty(&mut self) { self.left.component.set_dirty(); self.right.component.set_dirty(); } + + fn get_shortcuts(&self) -> ShortcutMap { + let mut right_map = self.right.get_shortcuts(); + right_map.extend(self.left.get_shortcuts().into_iter()); + right_map + } } #[derive(Debug)] @@ -632,6 +649,10 @@ impl Component for StatusBar { fn set_dirty(&mut self) { self.dirty = true; } + + fn get_shortcuts(&self) -> ShortcutMap { + self.container.get_shortcuts() + } } // A box with a text content. @@ -718,6 +739,8 @@ impl Component for Progress { pub struct Tabbed { children: Vec<Entity>, cursor_pos: usize, + + show_shortcuts: bool, } impl Tabbed { @@ -725,6 +748,7 @@ impl Tabbed { Tabbed { children: children.into_iter().map(Entity::from).collect(), cursor_pos: 0, + show_shortcuts: false, } } fn draw_tabs(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { @@ -791,6 +815,34 @@ impl Component for Tabbed { } else { self.children[self.cursor_pos].draw(grid, area, context); } + + if self.show_shortcuts { + let area = ( + pos_inc(upper_left!(area), (2, 1)), set_x(bottom_right!(area), get_x(bottom_right!(area)).saturating_sub(2))); + clear_area(grid, area); + create_box(grid, area); + + // TODO: print into a pager + for (idx, (k, v)) in self.children[self.cursor_pos].get_shortcuts().into_iter().enumerate() { + let (x, y) = write_string_to_grid( + &format!("{:?}", k), + grid, + Color::Byte(29), + Color::Default, + (pos_inc(upper_left!(area), (2, 1 + idx)), set_x(bottom_right!(area), get_x(bottom_right!(area)).saturating_sub(2))), + false, + ); + write_string_to_grid( + &v, + grid, + Color::Default, + Color::Default, + ((x + 2, y), set_x(bottom_right!(area), get_x(bottom_right!(area)).saturating_sub(2))), + false, + ); + }; + context.dirty_areas.push_back(area); + } } fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { match event.event_type { @@ -799,6 +851,11 @@ impl Component for Tabbed { self.set_dirty(); return true; } + UIEventType::Input(Key::Char('?')) => { + self.show_shortcuts = !self.show_shortcuts; + self.set_dirty(); + return true; + } UIEventType::Action(Tab(NewDraft)) => { self.add_component(Box::new(Composer::default())); self.cursor_pos = self.children.len() - 1; diff --git a/ui/src/types/keys.rs b/ui/src/types/keys.rs index 722548b1..335e856e 100644 --- a/ui/src/types/keys.rs +++ b/ui/src/types/keys.rs @@ -26,7 +26,7 @@ use termion::event::Event as TermionEvent; use termion::event::Key as TermionKey; use termion::input::TermRead; -#[derive(Debug)] +#[derive(Debug, PartialEq, Eq, Hash, Clone)] pub enum Key { /// Backspace. Backspace, |