summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authorManos Pitsidianakis <el13635@mail.ntua.gr>2019-03-02 19:25:11 +0200
committerManos Pitsidianakis <el13635@mail.ntua.gr>2019-06-10 19:40:38 +0300
commitd285913974b418bde8fa94688d59522aae68dc66 (patch)
tree1107d7c411add0bfc4a8a173296cf33964630ea6 /ui
parent12cc9950c72b41b73c79160cc0f09617c01c644a (diff)
Add shortcut panel
Concerns #63
Diffstat (limited to 'ui')
-rw-r--r--ui/src/components.rs5
-rw-r--r--ui/src/components/mail/listing.rs8
-rw-r--r--ui/src/components/mail/listing/compact.rs17
-rw-r--r--ui/src/components/utilities.rs57
-rw-r--r--ui/src/types/keys.rs2
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,