From 11aac5ec34b9151cf688ce3c783dc93bd8a9421f Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Sat, 14 Jul 2018 18:03:43 +0300 Subject: [PATCH] Fix pager content drawing --- src/conf/mod.rs | 16 +++----------- src/conf/pager.rs | 24 ++++++++++++++++----- src/ui/components/mail.rs | 33 +++++++++++++++++----------- src/ui/components/mod.rs | 9 +++++--- src/ui/components/utilities.rs | 39 +++++++++++++++++----------------- 5 files changed, 69 insertions(+), 52 deletions(-) diff --git a/src/conf/mod.rs b/src/conf/mod.rs index 9678d8bde..7ed9a0aaa 100644 --- a/src/conf/mod.rs +++ b/src/conf/mod.rs @@ -69,10 +69,9 @@ struct FileAccount { } -#[derive(Debug, Deserialize, Default)] +#[derive(Debug, Deserialize)] struct FileSettings { accounts: HashMap, - #[serde(default)] pager: PagerSettings, } @@ -113,18 +112,8 @@ impl FileSettings { let mut s = Config::new(); let s = s.merge(File::new(config_path.to_str().unwrap(), FileFormat::Toml)); - if s.is_ok() { + // TODO: Return result s.unwrap().deserialize().unwrap() - } else { - eprintln!("{:?}", s.err().unwrap()); - let mut buf = String::new(); - io::stdin() - .read_line(&mut buf) - .expect("Failed to read line"); - FileSettings { - ..Default::default() - } - } } } @@ -175,6 +164,7 @@ impl Settings { }, ); } + eprintln!("pager settings are {:?}", fs.pager); Settings { accounts: s, pager: fs.pager } } diff --git a/src/conf/pager.rs b/src/conf/pager.rs index ec32918f3..2b95f5faf 100644 --- a/src/conf/pager.rs +++ b/src/conf/pager.rs @@ -1,24 +1,38 @@ fn false_val () -> bool { - false + true +} + +fn true_val () -> bool { + true } fn zero_val () -> usize { 0 } +fn eighty_percent () -> usize { + 80 +} /// Settings for the pager function. -#[derive(Debug, Deserialize, Default)] +#[derive(Debug, Deserialize)] pub struct PagerSettings { - #[serde(default = "zero_val")] /// Number of context lines when going to next page. /// Default: 0 + #[serde(default = "zero_val")] pub pager_context: usize, - #[serde(default = "false_val")] /// Stop at the end instead of displaying next mail. /// Default: false + #[serde(default = "false_val")] pub pager_stop: bool, + /// Always show headers when scrolling. - /// Default: false + /// Default: true + #[serde(default = "true_val")] pub headers_sticky: bool, + + /// The height of the pager in mail view, in percent. + /// Default: 80 + #[serde(default = "eighty_percent")] + pub pager_ratio: usize, } diff --git a/src/ui/components/mail.rs b/src/ui/components/mail.rs index e73026a1a..8bb98d4d1 100644 --- a/src/ui/components/mail.rs +++ b/src/ui/components/mail.rs @@ -156,12 +156,12 @@ impl MailListing { let upper_left = upper_left!(area); let bottom_right = bottom_right!(area); - let ref mail = self.mailbox.collection[self.cursor_pos]; + let envelope: &Envelope = &self.mailbox.collection[self.cursor_pos]; let rows = get_y(bottom_right) - get_y(upper_left); let cols = get_x(bottom_right) - get_x(upper_left); - self.pager = Some(Pager::new(mail, rows, cols)); + self.pager = Some(Pager::new(envelope)); self.pager.as_mut().map(|p| p.draw(grid, area, context)); } } @@ -186,16 +186,26 @@ impl Component for MailListing { clear_area(grid, area); context.dirty_areas.push_back(area); } + let headers_rows: usize = 6; /* Render the mail body in a pager, basically copy what HSplit does */ let total_rows = get_y(bottom_right) - get_y(upper_left); /* TODO: define ratio in Configuration file */ - let bottom_entity_rows = (80*total_rows )/100; + let pager_ratio = context.settings.pager.pager_ratio; + let mut bottom_entity_rows = (pager_ratio*total_rows )/100; + if bottom_entity_rows < headers_rows + 2 { + bottom_entity_rows = headers_rows + 2; + } + if bottom_entity_rows > total_rows { + clear_area(grid, area); + context.dirty_areas.push_back(area); + return; + } let mid = get_y(upper_left) + total_rows - bottom_entity_rows; if !self.dirty { if let Some(ref mut p) = self.pager { p.draw(grid, - ((get_x(upper_left), get_y(upper_left) + mid+6), bottom_right), + ((get_x(upper_left), get_y(upper_left) + mid + headers_rows + 1), bottom_right), context); } return; @@ -215,12 +225,11 @@ impl Component for MailListing { } } - for i in get_x(upper_left)..get_x(bottom_right) { + for i in get_x(upper_left)..=get_x(bottom_right) { grid[(i, mid)].set_ch('─'); } } - let headers_rows: usize = 6; /* Draw header */ { let ref mail = self.mailbox.collection[self.cursor_pos]; @@ -231,7 +240,7 @@ impl Component for MailListing { Color::Byte(33), Color::Default, (set_y(upper_left, mid+1), set_y(bottom_right, mid+1))); - for x in x..get_x(bottom_right) { + for x in x..=get_x(bottom_right) { grid[(x, mid+1)].set_ch(' '); grid[(x, mid+1)].set_bg(Color::Default); grid[(x, mid+1)].set_fg(Color::Default); @@ -241,7 +250,7 @@ impl Component for MailListing { Color::Byte(33), Color::Default, (set_y(upper_left, mid+2), set_y(bottom_right, mid+2))); - for x in x..get_x(bottom_right) { + for x in x..=get_x(bottom_right) { grid[(x, mid+2)].set_ch(' '); grid[(x, mid+2)].set_bg(Color::Default); grid[(x, mid+2)].set_fg(Color::Default); @@ -251,7 +260,7 @@ impl Component for MailListing { Color::Byte(33), Color::Default, (set_y(upper_left, mid+3), set_y(bottom_right, mid+3))); - for x in x..get_x(bottom_right) { + for x in x..=get_x(bottom_right) { grid[(x, mid+3)].set_ch(' '); grid[(x, mid+3)].set_bg(Color::Default); grid[(x, mid+3)].set_fg(Color::Default); @@ -261,7 +270,7 @@ impl Component for MailListing { Color::Byte(33), Color::Default, (set_y(upper_left, mid+4), set_y(bottom_right, mid+4))); - for x in x..get_x(bottom_right) { + for x in x..=get_x(bottom_right) { grid[(x, mid+4)].set_ch(' '); grid[(x, mid+4)].set_bg(Color::Default); grid[(x, mid+4)].set_fg(Color::Default); @@ -271,7 +280,7 @@ impl Component for MailListing { Color::Byte(33), Color::Default, (set_y(upper_left, mid+5), set_y(bottom_right, mid+5))); - for x in x..get_x(bottom_right) { + for x in x..=get_x(bottom_right) { grid[(x, mid+5)].set_ch(' '); grid[(x, mid+5)].set_bg(Color::Default); grid[(x, mid+5)].set_fg(Color::Default); @@ -281,7 +290,7 @@ impl Component for MailListing { /* Draw body */ self.draw_mail_view(grid, - ((get_x(upper_left), get_y(upper_left) + mid + headers_rows), bottom_right), + ((get_x(upper_left), get_y(upper_left) + mid + headers_rows + 1), bottom_right), context); } diff --git a/src/ui/components/mod.rs b/src/ui/components/mod.rs index f97c6bada..46c240609 100644 --- a/src/ui/components/mod.rs +++ b/src/ui/components/mod.rs @@ -88,10 +88,12 @@ pub trait Component { fn write_string_to_grid(s: &str, grid: &mut CellBuffer, fg_color: Color, bg_color: Color, area: Area) -> usize { + let bounds = grid.size(); let upper_left = upper_left!(area); let bottom_right = bottom_right!(area); let (mut x, mut y) = upper_left; - if y > (get_y(bottom_right)) || x > get_x(bottom_right) { + if y > (get_y(bottom_right)) || x > get_x(bottom_right) || + y > get_y(bounds) || x > get_x(bounds) { return 0; } for c in s.chars() { @@ -99,10 +101,11 @@ fn write_string_to_grid(s: &str, grid: &mut CellBuffer, fg_color: Color, bg_colo grid[(x,y)].set_fg(fg_color); grid[(x,y)].set_bg(bg_color); x += 1; - if x == (get_x(bottom_right))+1 { + + if x == (get_x(bottom_right))+1 || x > get_x(bounds) { x = get_x(upper_left); y += 1; - if y == (get_y(bottom_right))+1 { + if y == (get_y(bottom_right))+1 || y > get_y(bounds) { return x; } } diff --git a/src/ui/components/utilities.rs b/src/ui/components/utilities.rs index d68151db9..210294575 100644 --- a/src/ui/components/utilities.rs +++ b/src/ui/components/utilities.rs @@ -183,31 +183,30 @@ impl Component for TextBox { /// current view of the text. It is responsible for scrolling etc. pub struct Pager { cursor_pos: usize, - lines_no: usize, - rows: usize, - cols: usize, + height: usize, + width: usize, dirty: bool, content: CellBuffer, } impl Pager { - pub fn new(mail: &Envelope, rows: usize, cols: usize) -> Self { + pub fn new(mail: &Envelope) -> Self { let text = mail.get_body().get_text(); let lines: Vec<&str> = text.trim().split('\n').collect(); - let lines_no = lines.len(); - let mut content = CellBuffer::new(cols, rows, Cell::with_char(' ')); + let height = lines.len(); + let width = lines.iter().map(|l| l.len()).max().unwrap_or(0); + let mut content = CellBuffer::new(width, height, Cell::with_char(' ')); for (i, l) in lines.iter().enumerate() { write_string_to_grid(l, &mut content, Color::Default, Color::Default, - ((0, i), (cols-1, rows-1))); + ((0, i), (width -1, i))); } Pager { cursor_pos: 0, - lines_no: lines_no, - rows: rows, - cols: cols, + height: height, + width: width, dirty: true, content: content, } @@ -222,23 +221,24 @@ impl Component for Pager { let upper_left = upper_left!(area); let bottom_right = bottom_right!(area); clear_area(grid, - ((get_x(upper_left), get_y(upper_left)-1), bottom_right)); - context.dirty_areas.push_back(((get_x(upper_left), get_y(upper_left)-1), bottom_right)); + (upper_left, bottom_right)); + context.dirty_areas.push_back((upper_left, bottom_right)); - if self.lines_no == 0 { + if self.height == 0 { return; } - let pager_context = context.settings.pager.pager_context; + let pager_context: usize = context.settings.pager.pager_context; + let pager_stop: bool = context.settings.pager.pager_stop; let rows = get_y(bottom_right) - get_y(upper_left); - let page_length = rows / self.lines_no; + let page_length = rows / self.height; self.dirty = false; let mut inner_x = 0; let mut inner_y = self.cursor_pos; for y in get_y(upper_left)..=get_y(bottom_right) { 'for_x: for x in get_x(upper_left)..=get_x(bottom_right) { - if inner_x == self.cols { + if inner_x == self.width { break 'for_x; } grid[(x,y)] = self.content[(inner_x, inner_y)]; @@ -246,11 +246,11 @@ impl Component for Pager { } inner_y += 1; inner_x = 0; - if inner_y == self.rows { + if inner_y == self.height { break; } } - context.dirty_areas.push_back(area); + context.dirty_areas.push_back(area); } fn process_event(&mut self, event: &UIEvent, _context: &mut Context) { match event.event_type { @@ -261,8 +261,9 @@ impl Component for Pager { } }, UIEventType::Input(Key::Char('j')) => { - if self.rows > 0 && self.cursor_pos < self.rows - 1 { + if self.height > 0 && self.cursor_pos < self.height - 1 { self.cursor_pos += 1; + eprintln!("new pager cursor is {}", self.cursor_pos); self.dirty = true; } },