Fix pager content drawing

embed
Manos Pitsidianakis 2018-07-14 18:03:43 +03:00
parent d089eb49dc
commit 11aac5ec34
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
5 changed files with 69 additions and 52 deletions

View File

@ -69,10 +69,9 @@ struct FileAccount {
}
#[derive(Debug, Deserialize, Default)]
#[derive(Debug, Deserialize)]
struct FileSettings {
accounts: HashMap<String, FileAccount>,
#[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 }
}

View File

@ -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,
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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;
}
},