Fix pager content drawing

embed
Manos Pitsidianakis 6 years ago
parent d089eb49dc
commit 11aac5ec34
No known key found for this signature in database
GPG Key ID: 73627C2F690DF710

@ -69,10 +69,9 @@ struct FileAccount {
} }
#[derive(Debug, Deserialize, Default)] #[derive(Debug, Deserialize)]
struct FileSettings { struct FileSettings {
accounts: HashMap<String, FileAccount>, accounts: HashMap<String, FileAccount>,
#[serde(default)]
pager: PagerSettings, pager: PagerSettings,
} }
@ -113,18 +112,8 @@ impl FileSettings {
let mut s = Config::new(); let mut s = Config::new();
let s = s.merge(File::new(config_path.to_str().unwrap(), FileFormat::Toml)); let s = s.merge(File::new(config_path.to_str().unwrap(), FileFormat::Toml));
if s.is_ok() { // TODO: Return result
s.unwrap().deserialize().unwrap() 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 } Settings { accounts: s, pager: fs.pager }
} }

@ -1,24 +1,38 @@
fn false_val () -> bool { fn false_val () -> bool {
false true
}
fn true_val () -> bool {
true
} }
fn zero_val () -> usize { fn zero_val () -> usize {
0 0
} }
fn eighty_percent () -> usize {
80
}
/// Settings for the pager function. /// Settings for the pager function.
#[derive(Debug, Deserialize, Default)] #[derive(Debug, Deserialize)]
pub struct PagerSettings { pub struct PagerSettings {
#[serde(default = "zero_val")]
/// Number of context lines when going to next page. /// Number of context lines when going to next page.
/// Default: 0 /// Default: 0
#[serde(default = "zero_val")]
pub pager_context: usize, pub pager_context: usize,
#[serde(default = "false_val")]
/// Stop at the end instead of displaying next mail. /// Stop at the end instead of displaying next mail.
/// Default: false /// Default: false
#[serde(default = "false_val")]
pub pager_stop: bool, pub pager_stop: bool,
/// Always show headers when scrolling. /// Always show headers when scrolling.
/// Default: false /// Default: true
#[serde(default = "true_val")]
pub headers_sticky: bool, pub headers_sticky: bool,
/// The height of the pager in mail view, in percent.
/// Default: 80
#[serde(default = "eighty_percent")]
pub pager_ratio: usize,
} }

@ -156,12 +156,12 @@ impl MailListing {
let upper_left = upper_left!(area); let upper_left = upper_left!(area);
let bottom_right = bottom_right!(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 rows = get_y(bottom_right) - get_y(upper_left);
let cols = get_x(bottom_right) - get_x(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)); self.pager.as_mut().map(|p| p.draw(grid, area, context));
} }
} }
@ -186,16 +186,26 @@ impl Component for MailListing {
clear_area(grid, area); clear_area(grid, area);
context.dirty_areas.push_back(area); context.dirty_areas.push_back(area);
} }
let headers_rows: usize = 6;
/* Render the mail body in a pager, basically copy what HSplit does */ /* Render the mail body in a pager, basically copy what HSplit does */
let total_rows = get_y(bottom_right) - get_y(upper_left); let total_rows = get_y(bottom_right) - get_y(upper_left);
/* TODO: define ratio in Configuration file */ /* 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; let mid = get_y(upper_left) + total_rows - bottom_entity_rows;
if !self.dirty { if !self.dirty {
if let Some(ref mut p) = self.pager { if let Some(ref mut p) = self.pager {
p.draw(grid, 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); context);
} }
return; 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('─'); grid[(i, mid)].set_ch('─');
} }
} }
let headers_rows: usize = 6;
/* Draw header */ /* Draw header */
{ {
let ref mail = self.mailbox.collection[self.cursor_pos]; let ref mail = self.mailbox.collection[self.cursor_pos];
@ -231,7 +240,7 @@ impl Component for MailListing {
Color::Byte(33), Color::Byte(33),
Color::Default, Color::Default,
(set_y(upper_left, mid+1), set_y(bottom_right, mid+1))); (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_ch(' ');
grid[(x, mid+1)].set_bg(Color::Default); grid[(x, mid+1)].set_bg(Color::Default);
grid[(x, mid+1)].set_fg(Color::Default); grid[(x, mid+1)].set_fg(Color::Default);
@ -241,7 +250,7 @@ impl Component for MailListing {
Color::Byte(33), Color::Byte(33),
Color::Default, Color::Default,
(set_y(upper_left, mid+2), set_y(bottom_right, mid+2))); (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_ch(' ');
grid[(x, mid+2)].set_bg(Color::Default); grid[(x, mid+2)].set_bg(Color::Default);
grid[(x, mid+2)].set_fg(Color::Default); grid[(x, mid+2)].set_fg(Color::Default);
@ -251,7 +260,7 @@ impl Component for MailListing {
Color::Byte(33), Color::Byte(33),
Color::Default, Color::Default,
(set_y(upper_left, mid+3), set_y(bottom_right, mid+3))); (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_ch(' ');
grid[(x, mid+3)].set_bg(Color::Default); grid[(x, mid+3)].set_bg(Color::Default);
grid[(x, mid+3)].set_fg(Color::Default); grid[(x, mid+3)].set_fg(Color::Default);
@ -261,7 +270,7 @@ impl Component for MailListing {
Color::Byte(33), Color::Byte(33),
Color::Default, Color::Default,
(set_y(upper_left, mid+4), set_y(bottom_right, mid+4))); (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_ch(' ');
grid[(x, mid+4)].set_bg(Color::Default); grid[(x, mid+4)].set_bg(Color::Default);
grid[(x, mid+4)].set_fg(Color::Default); grid[(x, mid+4)].set_fg(Color::Default);
@ -271,7 +280,7 @@ impl Component for MailListing {
Color::Byte(33), Color::Byte(33),
Color::Default, Color::Default,
(set_y(upper_left, mid+5), set_y(bottom_right, mid+5))); (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_ch(' ');
grid[(x, mid+5)].set_bg(Color::Default); grid[(x, mid+5)].set_bg(Color::Default);
grid[(x, mid+5)].set_fg(Color::Default); grid[(x, mid+5)].set_fg(Color::Default);
@ -281,7 +290,7 @@ impl Component for MailListing {
/* Draw body */ /* Draw body */
self.draw_mail_view(grid, 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); context);
} }

@ -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 { 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 upper_left = upper_left!(area);
let bottom_right = bottom_right!(area); let bottom_right = bottom_right!(area);
let (mut x, mut y) = upper_left; 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; return 0;
} }
for c in s.chars() { 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_fg(fg_color);
grid[(x,y)].set_bg(bg_color); grid[(x,y)].set_bg(bg_color);
x += 1; 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); x = get_x(upper_left);
y += 1; y += 1;
if y == (get_y(bottom_right))+1 { if y == (get_y(bottom_right))+1 || y > get_y(bounds) {
return x; return x;
} }
} }

@ -183,31 +183,30 @@ impl Component for TextBox {
/// current view of the text. It is responsible for scrolling etc. /// current view of the text. It is responsible for scrolling etc.
pub struct Pager { pub struct Pager {
cursor_pos: usize, cursor_pos: usize,
lines_no: usize, height: usize,
rows: usize, width: usize,
cols: usize,
dirty: bool, dirty: bool,
content: CellBuffer, content: CellBuffer,
} }
impl Pager { 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 text = mail.get_body().get_text();
let lines: Vec<&str> = text.trim().split('\n').collect(); let lines: Vec<&str> = text.trim().split('\n').collect();
let lines_no = lines.len(); let height = lines.len();
let mut content = CellBuffer::new(cols, rows, Cell::with_char(' ')); 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() { for (i, l) in lines.iter().enumerate() {
write_string_to_grid(l, write_string_to_grid(l,
&mut content, &mut content,
Color::Default, Color::Default,
Color::Default, Color::Default,
((0, i), (cols-1, rows-1))); ((0, i), (width -1, i)));
} }
Pager { Pager {
cursor_pos: 0, cursor_pos: 0,
lines_no: lines_no, height: height,
rows: rows, width: width,
cols: cols,
dirty: true, dirty: true,
content: content, content: content,
} }
@ -222,23 +221,24 @@ impl Component for Pager {
let upper_left = upper_left!(area); let upper_left = upper_left!(area);
let bottom_right = bottom_right!(area); let bottom_right = bottom_right!(area);
clear_area(grid, clear_area(grid,
((get_x(upper_left), get_y(upper_left)-1), bottom_right)); (upper_left, bottom_right));
context.dirty_areas.push_back(((get_x(upper_left), get_y(upper_left)-1), bottom_right)); context.dirty_areas.push_back((upper_left, bottom_right));
if self.lines_no == 0 { if self.height == 0 {
return; 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 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; self.dirty = false;
let mut inner_x = 0; let mut inner_x = 0;
let mut inner_y = self.cursor_pos; let mut inner_y = self.cursor_pos;
for y in get_y(upper_left)..=get_y(bottom_right) { for y in get_y(upper_left)..=get_y(bottom_right) {
'for_x: for x in get_x(upper_left)..=get_x(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; break 'for_x;
} }
grid[(x,y)] = self.content[(inner_x, inner_y)]; grid[(x,y)] = self.content[(inner_x, inner_y)];
@ -246,11 +246,11 @@ impl Component for Pager {
} }
inner_y += 1; inner_y += 1;
inner_x = 0; inner_x = 0;
if inner_y == self.rows { if inner_y == self.height {
break; break;
} }
} }
context.dirty_areas.push_back(area); context.dirty_areas.push_back(area);
} }
fn process_event(&mut self, event: &UIEvent, _context: &mut Context) { fn process_event(&mut self, event: &UIEvent, _context: &mut Context) {
match event.event_type { match event.event_type {
@ -261,8 +261,9 @@ impl Component for Pager {
} }
}, },
UIEventType::Input(Key::Char('j')) => { 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; self.cursor_pos += 1;
eprintln!("new pager cursor is {}", self.cursor_pos);
self.dirty = true; self.dirty = true;
} }
}, },

Loading…
Cancel
Save