Fix pager content drawing
parent
d089eb49dc
commit
11aac5ec34
|
@ -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 }
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in New Issue