parent
ea65989679
commit
bbd1918d70
|
@ -218,23 +218,33 @@ impl Composer {
|
|||
|
||||
impl Component for Composer {
|
||||
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
|
||||
if !self.initialized {
|
||||
self.update_form();
|
||||
self.initialized = true;
|
||||
}
|
||||
clear_area(grid, area);
|
||||
|
||||
let upper_left = upper_left!(area);
|
||||
let bottom_right = bottom_right!(area);
|
||||
|
||||
let upper_left = set_y(upper_left, get_y(upper_left) + 1);
|
||||
let header_height = self.form.len() + 1;
|
||||
|
||||
if self.dirty {
|
||||
self.draft.headers_mut().insert(
|
||||
"From".into(),
|
||||
get_display_name(context, self.account_cursor),
|
||||
);
|
||||
self.dirty = false;
|
||||
}
|
||||
|
||||
let width = if width!(area) > 80 && self.reply_context.is_some() {
|
||||
width!(area) / 2
|
||||
} else {
|
||||
width!(area)
|
||||
};
|
||||
|
||||
if !self.initialized {
|
||||
self.pager.update_from_str(self.draft.body(), Some(77));
|
||||
self.update_form();
|
||||
self.initialized = true;
|
||||
}
|
||||
let header_height = self.form.len() + 1;
|
||||
|
||||
let mid = if width > 80 {
|
||||
let width = width - 80;
|
||||
let mid = if self.reply_context.is_some() {
|
||||
|
@ -273,27 +283,19 @@ impl Component for Composer {
|
|||
}
|
||||
|
||||
if self.dirty {
|
||||
for i in get_x(upper_left) + mid + 1..=get_x(upper_left) + mid + 79 {
|
||||
for i in get_x(upper_left) + mid + 1..=get_x(upper_left) + mid + width.saturating_sub(0) {
|
||||
//set_and_join_box(grid, (i, header_height), HORZ_BOUNDARY);
|
||||
grid[(i, header_height)].set_fg(Color::Default);
|
||||
grid[(i, header_height)].set_bg(Color::Default);
|
||||
//grid[(i, header_height)].set_fg(Color::Default);
|
||||
//grid[(i, header_height)].set_bg(Color::Default);
|
||||
}
|
||||
}
|
||||
|
||||
let header_area = (set_x(upper_left, mid + 1), (mid + 78, header_height + 1));
|
||||
let header_area = (pos_inc(upper_left, (mid + 1, 0)), (get_x(bottom_right).saturating_sub(mid), get_y(upper_left) + header_height + 1));
|
||||
let body_area = (
|
||||
(mid + 1, header_height + 2),
|
||||
(mid + 78, get_y(bottom_right)),
|
||||
pos_inc(upper_left, (mid + 1, header_height + 2)),
|
||||
pos_dec(bottom_right, ((mid, 0))),
|
||||
);
|
||||
|
||||
if self.dirty {
|
||||
self.draft.headers_mut().insert(
|
||||
"From".into(),
|
||||
get_display_name(context, self.account_cursor),
|
||||
);
|
||||
self.dirty = false;
|
||||
}
|
||||
|
||||
/* Regardless of view mode, do the following */
|
||||
self.form.draw(grid, header_area, context);
|
||||
|
||||
|
@ -304,27 +306,18 @@ impl Component for Composer {
|
|||
},
|
||||
ViewMode::Discard(_) => {
|
||||
/* Let user choose whether to quit with/without saving or cancel */
|
||||
let mid_x = width!(area) / 2;
|
||||
let mid_y = height!(area) / 2;
|
||||
for x in mid_x - 40..=mid_x + 40 {
|
||||
for y in mid_y - 11..=mid_y + 11 {
|
||||
grid[(x, y)] = Cell::default();
|
||||
}
|
||||
}
|
||||
let mid_x = {
|
||||
std::cmp::max(width!(area) / 2, width / 2) - width / 2
|
||||
};
|
||||
let mid_y = {
|
||||
std::cmp::max(height!(area) / 2, 11) - 11
|
||||
};
|
||||
|
||||
for i in mid_x - 40..=mid_x + 40 {
|
||||
set_and_join_box(grid, (i, mid_y - 11), HORZ_BOUNDARY);
|
||||
|
||||
set_and_join_box(grid, (i, mid_y + 11), HORZ_BOUNDARY);
|
||||
}
|
||||
|
||||
for i in mid_y - 11..=mid_y + 11 {
|
||||
set_and_join_box(grid, (mid_x - 40, i), VERT_BOUNDARY);
|
||||
|
||||
set_and_join_box(grid, (mid_x + 40, i), VERT_BOUNDARY);
|
||||
}
|
||||
|
||||
let area = ((mid_x - 20, mid_y - 7), (mid_x + 39, mid_y + 10));
|
||||
let upper_left = upper_left!(body_area);
|
||||
let bottom_right = bottom_right!(body_area);
|
||||
let area = (pos_inc(upper_left, (mid_x, mid_y)), pos_dec(bottom_right, (mid_x, mid_y)));
|
||||
create_box(grid, area);
|
||||
let area = (pos_inc(upper_left, (mid_x + 2, mid_y + 2)), pos_dec(bottom_right, (mid_x.saturating_sub(2), mid_y.saturating_sub(2))));
|
||||
|
||||
let (_, y) = write_string_to_grid(
|
||||
&format!("Draft \"{:10}\"", self.draft.headers()["Subject"]),
|
||||
|
@ -483,8 +476,7 @@ impl Component for Composer {
|
|||
.expect("failed to execute process");
|
||||
let result = f.read_to_string();
|
||||
self.draft = Draft::from_str(result.as_str()).unwrap();
|
||||
self.pager.update_from_str(self.draft.body());
|
||||
self.update_form();
|
||||
self.initialized = false;
|
||||
context.replies.push_back(UIEvent {
|
||||
id: 0,
|
||||
event_type: UIEventType::Fork(ForkType::Finished),
|
||||
|
|
|
@ -377,9 +377,9 @@ impl Component for EnvelopeView {
|
|||
match u.content_type() {
|
||||
ContentType::MessageRfc822 => {
|
||||
self.mode = ViewMode::Subview;
|
||||
self.subview = Some(Box::new(Pager::from_str(
|
||||
&String::from_utf8_lossy(&decode_rec(u, None)).to_string(),
|
||||
None,
|
||||
self.subview = Some(Box::new(Pager::from_string(
|
||||
String::from_utf8_lossy(&decode_rec(u, None)).to_string(), context,
|
||||
None, None
|
||||
)));
|
||||
}
|
||||
|
||||
|
|
|
@ -215,10 +215,10 @@ pub enum PageMovement {
|
|||
/// current view of the text. It is responsible for scrolling etc.
|
||||
#[derive(Default, Debug)]
|
||||
pub struct Pager {
|
||||
text: String,
|
||||
cursor_pos: usize,
|
||||
max_cursor_pos: Option<usize>,
|
||||
height: usize,
|
||||
|
||||
width: usize,
|
||||
dirty: bool,
|
||||
content: CellBuffer,
|
||||
|
@ -233,13 +233,18 @@ impl fmt::Display for Pager {
|
|||
}
|
||||
|
||||
impl Pager {
|
||||
pub fn update_from_str(&mut self, text: &str) {
|
||||
let lines: Vec<&str> = text.trim().split('\n').collect();
|
||||
pub fn update_from_str(&mut self, text: &str, width: Option<usize>) {
|
||||
let lines: Vec<&str> = if let Some(width) = width {
|
||||
word_break_string(text, width)
|
||||
} else {
|
||||
text.trim().split('\n').collect()
|
||||
};
|
||||
|
||||
let height = lines.len() + 1;
|
||||
let width = lines.iter().map(|l| l.len()).max().unwrap_or(0);
|
||||
let width = width.unwrap_or_else(|| lines.iter().map(|l| l.len()).max().unwrap_or(0));
|
||||
let mut content = CellBuffer::new(width, height, Cell::with_char(' '));
|
||||
//interpret_format_flowed(&text);
|
||||
Pager::print_string(&mut content, text);
|
||||
Pager::print_string(&mut content, lines);
|
||||
self.text = text.to_string();
|
||||
self.content = content;
|
||||
self.height = height;
|
||||
self.width = width;
|
||||
|
@ -247,7 +252,7 @@ impl Pager {
|
|||
self.cursor_pos = 0;
|
||||
self.max_cursor_pos = None;
|
||||
}
|
||||
pub fn from_string(mut text: String, context: &mut Context, cursor_pos: Option<usize>) -> Self {
|
||||
pub fn from_string(mut text: String, context: &mut Context, cursor_pos: Option<usize>, width: Option<usize>) -> Self {
|
||||
let pager_filter: Option<&String> = context.settings.pager.filter.as_ref();
|
||||
//let format_flowed: bool = context.settings.pager.format_flowed;
|
||||
if let Some(bin) = pager_filter {
|
||||
|
@ -273,28 +278,45 @@ impl Pager {
|
|||
).to_string();
|
||||
}
|
||||
|
||||
let lines: Vec<&str> = text.trim().split('\n').collect();
|
||||
let height = lines.len() + 1;
|
||||
let width = lines.iter().map(|l| l.len()).max().unwrap_or(0);
|
||||
let mut content = CellBuffer::new(width, height, Cell::with_char(' '));
|
||||
//interpret_format_flowed(&text);
|
||||
Pager::print_string(&mut content, &text);
|
||||
|
||||
let content = {
|
||||
let lines: Vec<&str> = if let Some(width) = width {
|
||||
word_break_string(text.as_str(), width)
|
||||
} else {
|
||||
text.trim().split('\n').collect()
|
||||
};
|
||||
|
||||
let height = lines.len() + 1;
|
||||
let width = width.unwrap_or_else(|| lines.iter().map(|l| l.len()).max().unwrap_or(0));
|
||||
let mut content = CellBuffer::new(width, height, Cell::with_char(' '));
|
||||
//interpret_format_flowed(&text);
|
||||
Pager::print_string(&mut content, lines);
|
||||
content
|
||||
};
|
||||
Pager {
|
||||
text: text,
|
||||
cursor_pos: cursor_pos.unwrap_or(0),
|
||||
height,
|
||||
width,
|
||||
height: content.size().1,
|
||||
width: content.size().0,
|
||||
dirty: true,
|
||||
content,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
pub fn from_str(s: &str, cursor_pos: Option<usize>) -> Self {
|
||||
let lines: Vec<&str> = s.trim().split('\n').collect();
|
||||
let height = lines.len();
|
||||
let width = lines.iter().map(|l| l.len()).max().unwrap_or(0);
|
||||
pub fn from_str(text: &str, cursor_pos: Option<usize>, width: Option<usize>) -> Self {
|
||||
let lines: Vec<&str> = if let Some(width) = width {
|
||||
word_break_string(text, width)
|
||||
} else {
|
||||
text.trim().split('\n').collect()
|
||||
};
|
||||
|
||||
let height = lines.len() + 1;
|
||||
let width = width.unwrap_or_else(|| lines.iter().map(|l| l.len()).max().unwrap_or(0));
|
||||
let mut content = CellBuffer::new(width, height, Cell::with_char(' '));
|
||||
Pager::print_string(&mut content, s);
|
||||
|
||||
Pager::print_string(&mut content, lines);
|
||||
Pager {
|
||||
text: text.to_string(),
|
||||
cursor_pos: cursor_pos.unwrap_or(0),
|
||||
height,
|
||||
width,
|
||||
|
@ -306,6 +328,7 @@ impl Pager {
|
|||
pub fn from_buf(content: CellBuffer, cursor_pos: Option<usize>) -> Self {
|
||||
let (width, height) = content.size();
|
||||
Pager {
|
||||
text: String::new(),
|
||||
cursor_pos: cursor_pos.unwrap_or(0),
|
||||
height,
|
||||
width,
|
||||
|
@ -314,20 +337,17 @@ impl Pager {
|
|||
..Default::default()
|
||||
}
|
||||
}
|
||||
pub fn print_string(content: &mut CellBuffer, s: &str) {
|
||||
let lines: Vec<&str> = s.trim().split('\n').collect();
|
||||
let width = lines.iter().map(|l| l.len()).max().unwrap_or(0);
|
||||
if width > 0 {
|
||||
for (i, l) in lines.iter().enumerate() {
|
||||
write_string_to_grid(
|
||||
l,
|
||||
content,
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
((0, i), (width - 1, i)),
|
||||
true,
|
||||
pub fn print_string(content: &mut CellBuffer, lines: Vec<&str>) {
|
||||
let width = content.size().0;
|
||||
for (i, l) in lines.iter().enumerate() {
|
||||
write_string_to_grid(
|
||||
l,
|
||||
content,
|
||||
Color::Default,
|
||||
Color::Default,
|
||||
((0, i), (width - 1, i)),
|
||||
true,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn cursor_pos(&self) -> usize {
|
||||
|
@ -386,6 +406,17 @@ impl Component for Pager {
|
|||
//let pager_stop: bool = context.settings.pager.pager_stop;
|
||||
//let rows = y(bottom_right) - y(upper_left);
|
||||
//let page_length = rows / self.height;
|
||||
let width = width!(area);
|
||||
if width != self.width {
|
||||
// Reflow text.
|
||||
let lines: Vec<&str> = word_break_string(self.text.as_str(), width);
|
||||
let height = lines.len() + 1;
|
||||
self.width = width;
|
||||
self.height = height;
|
||||
self.content = CellBuffer::new(width, height, Cell::with_char(' '));
|
||||
Pager::print_string(&mut self.content, lines);
|
||||
}
|
||||
|
||||
let pos = copy_area_with_break(
|
||||
grid,
|
||||
&self.content,
|
||||
|
@ -788,7 +819,9 @@ impl Tabbed {
|
|||
}
|
||||
let (cols, _) = grid.size();
|
||||
let cslice: &mut [Cell] = grid;
|
||||
for c in cslice[(y * cols) + x - 1..(y * cols) + cols].iter_mut() {
|
||||
//TODO: bounds check
|
||||
let cslice_len = cslice.len();
|
||||
for c in cslice[(y * cols) + x.saturating_sub(1)..std::cmp::min((y * cols) + x.saturating_sub(1), cslice_len)].iter_mut() {
|
||||
c.set_bg(Color::Byte(7));
|
||||
c.set_ch(' ');
|
||||
}
|
||||
|
|
|
@ -702,10 +702,14 @@ pub fn write_string_to_grid(
|
|||
let upper_left = upper_left!(area);
|
||||
let bottom_right = bottom_right!(area);
|
||||
let (mut x, mut y) = upper_left;
|
||||
if y == get_y(bounds) || x == get_x(bounds) {
|
||||
return (x, y);
|
||||
}
|
||||
|
||||
if y > (get_y(bottom_right))
|
||||
|| x > get_x(bottom_right)
|
||||
|| y >= get_y(bounds)
|
||||
|| x >= get_x(bounds)
|
||||
|| y > get_y(bounds)
|
||||
|| x > get_x(bounds)
|
||||
{
|
||||
eprintln!(" Invalid area with string {} and area {:?}", s, area);
|
||||
return (x, y);
|
||||
|
|
|
@ -49,6 +49,11 @@ pub fn pos_inc(p: Pos, inc: (usize, usize)) -> Pos {
|
|||
(p.0 + inc.0, p.1 + inc.1)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn pos_dec(p: Pos, dec: (usize, usize)) -> Pos {
|
||||
(p.0.saturating_sub(dec.0), p.1.saturating_sub(dec.1))
|
||||
}
|
||||
|
||||
/// An `Area` consists of two points: the upper left and bottom right corners.
|
||||
///
|
||||
/// Example:
|
||||
|
|
Loading…
Reference in New Issue