ui: add ThemeAttribute argument to clear_area()

clear_area() sets the cleared cell attributes according to the new
argument.
memfd
Manos Pitsidianakis 2020-02-08 13:40:47 +02:00
parent 3bca6d1d9c
commit eb501b6d50
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
16 changed files with 273 additions and 154 deletions

View File

@ -151,6 +151,7 @@ impl Component for ContactManager {
clear_area(
grid,
(upper_left, set_y(bottom_right, get_y(upper_left) + 1)),
Default::default(),
);
copy_area_with_break(grid, &self.content, area, ((0, 0), (width - 1, 0)));
self.dirty = false;

View File

@ -48,6 +48,7 @@ pub struct ContactList {
length: usize,
data_columns: DataColumns,
initialized: bool,
theme_default: ThemeAttribute,
id_positions: Vec<CardId>,
@ -89,6 +90,7 @@ impl ContactList {
id_positions: Vec::new(),
mode: ViewMode::List,
data_columns: DataColumns::default(),
theme_default: crate::conf::value(context, "theme_default"),
initialized: false,
dirty: true,
movement: None,
@ -156,9 +158,9 @@ impl ContactList {
write_string_to_grid(
c.name(),
&mut self.data_columns.columns[0],
Color::Default,
Color::Default,
Attr::Default,
self.theme_default.fg,
self.theme_default.bg,
self.theme_default.attrs,
((0, idx), (min_width.0, idx)),
None,
);
@ -166,9 +168,9 @@ impl ContactList {
write_string_to_grid(
c.email(),
&mut self.data_columns.columns[1],
Color::Default,
Color::Default,
Attr::Default,
self.theme_default.fg,
self.theme_default.bg,
self.theme_default.attrs,
((0, idx), (min_width.1, idx)),
None,
);
@ -176,9 +178,9 @@ impl ContactList {
write_string_to_grid(
c.url(),
&mut self.data_columns.columns[2],
Color::Default,
Color::Default,
Attr::Default,
self.theme_default.fg,
self.theme_default.bg,
self.theme_default.attrs,
((0, idx), (min_width.2, idx)),
None,
);
@ -190,9 +192,9 @@ impl ContactList {
"local"
},
&mut self.data_columns.columns[3],
Color::Default,
Color::Default,
Attr::Default,
self.theme_default.fg,
self.theme_default.bg,
self.theme_default.attrs,
((0, idx), (min_width.3, idx)),
None,
);
@ -209,9 +211,9 @@ impl ContactList {
write_string_to_grid(
&message,
&mut self.data_columns.columns[0],
Color::Default,
Color::Default,
Attr::Default,
self.theme_default.fg,
self.theme_default.bg,
self.theme_default.attrs,
((0, 0), (MAX_COLS - 1, 0)),
None,
);
@ -221,11 +223,11 @@ impl ContactList {
fn highlight_line(&mut self, grid: &mut CellBuffer, area: Area, idx: usize) {
/* Reset previously highlighted line */
let fg_color = Color::Default;
let fg_color = self.theme_default.fg;
let bg_color = if idx == self.new_cursor_pos {
Color::Byte(246)
} else {
Color::Default
self.theme_default.bg
};
change_colors(grid, area, fg_color, bg_color);
}
@ -234,7 +236,7 @@ impl ContactList {
if !self.is_dirty() {
return;
}
clear_area(grid, area);
clear_area(grid, area, self.theme_default);
/* visually divide menu and listing */
area = (area.0, pos_dec(area.1, (1, 0)));
let upper_left = upper_left!(area);
@ -271,7 +273,7 @@ impl ContactList {
(Color::Byte(15), Color::Byte(233))
}
} else {
(Color::Default, Color::Default)
(self.theme_default.fg, self.theme_default.bg)
};
let s = format!(" [{}]", context.accounts[a.index].address_book.len());
@ -348,7 +350,7 @@ impl ContactList {
let bottom_right = bottom_right!(area);
if self.length == 0 {
clear_area(grid, area);
clear_area(grid, area, self.theme_default);
copy_area(
grid,
&self.data_columns.columns[0],
@ -441,7 +443,7 @@ impl ContactList {
width.saturating_sub(self.data_columns.widths[0] + self.data_columns.widths[1] + 4);
self.data_columns.widths[2] = remainder / 6;
}
clear_area(grid, area);
clear_area(grid, area, self.theme_default);
/* Page_no has changed, so draw new page */
let mut x = get_x(upper_left);
for i in 0..self.data_columns.columns.len() {
@ -511,6 +513,7 @@ impl ContactList {
pos_inc(upper_left, (0, self.length - top_idx + 2)),
bottom_right,
),
self.theme_default,
);
}
self.highlight_line(
@ -552,14 +555,16 @@ impl Component for ContactList {
if self.dirty && mid != get_x(upper_left) {
if self.show_divider {
for i in get_y(upper_left)..=get_y(bottom_right) {
grid[(mid, i)].set_ch(VERT_BOUNDARY);
grid[(mid, i)].set_fg(Color::Default);
grid[(mid, i)].set_bg(Color::Default);
grid[(mid, i)]
.set_ch(VERT_BOUNDARY)
.set_fg(self.theme_default.fg)
.set_bg(self.theme_default.bg);
}
} else {
for i in get_y(upper_left)..=get_y(bottom_right) {
grid[(mid, i)].set_fg(Color::Default);
grid[(mid, i)].set_bg(Color::Default);
grid[(mid, i)]
.set_fg(self.theme_default.fg)
.set_bg(self.theme_default.bg);
}
}
context

View File

@ -258,7 +258,8 @@ impl Composer {
fn draw_attachments(&self, grid: &mut CellBuffer, area: Area, context: &Context) {
let attachments_no = self.draft.attachments().len();
clear_area(grid, area);
let theme_default = crate::conf::value(context, "theme_default");
clear_area(grid, area, theme_default);
if self.sign_mail.is_true() {
write_string_to_grid(
&format!(
@ -272,9 +273,9 @@ impl Composer {
.unwrap_or("default key")
),
grid,
Color::Default,
Color::Default,
Attr::Default,
theme_default.fg,
theme_default.bg,
theme_default.attrs,
(pos_inc(upper_left!(area), (0, 1)), bottom_right!(area)),
None,
);
@ -282,9 +283,9 @@ impl Composer {
write_string_to_grid(
"☐ don't sign",
grid,
Color::Default,
Color::Default,
Attr::Default,
theme_default.fg,
theme_default.bg,
theme_default.attrs,
(pos_inc(upper_left!(area), (0, 1)), bottom_right!(area)),
None,
);
@ -293,9 +294,9 @@ impl Composer {
write_string_to_grid(
"no attachments",
grid,
Color::Default,
Color::Default,
Attr::Default,
theme_default.fg,
theme_default.bg,
theme_default.attrs,
(pos_inc(upper_left!(area), (0, 2)), bottom_right!(area)),
None,
);
@ -303,9 +304,9 @@ impl Composer {
write_string_to_grid(
&format!("{} attachments ", attachments_no),
grid,
Color::Default,
Color::Default,
Attr::Default,
theme_default.fg,
theme_default.bg,
theme_default.attrs,
(pos_inc(upper_left!(area), (0, 2)), bottom_right!(area)),
None,
);
@ -320,9 +321,9 @@ impl Composer {
a.raw.len()
),
grid,
Color::Default,
Color::Default,
Attr::Default,
theme_default.fg,
theme_default.bg,
theme_default.attrs,
(pos_inc(upper_left!(area), (0, 3 + i)), bottom_right!(area)),
None,
);
@ -330,9 +331,9 @@ impl Composer {
write_string_to_grid(
&format!("[{}] {} {} bytes", i, a.content_type(), a.raw.len()),
grid,
Color::Default,
Color::Default,
Attr::Default,
theme_default.fg,
theme_default.bg,
theme_default.attrs,
(pos_inc(upper_left!(area), (0, 3 + i)), bottom_right!(area)),
None,
);
@ -371,6 +372,7 @@ impl Component for Composer {
self.initialized = true;
}
let header_height = self.form.len();
let theme_default = crate::conf::value(context, "theme_default");
let mid = if width > 80 {
let width = width - 80;
@ -379,11 +381,13 @@ impl Component for Composer {
if self.dirty {
for i in get_y(upper_left)..=get_y(bottom_right) {
//set_and_join_box(grid, (mid, i), VERT_BOUNDARY);
grid[(mid, i)].set_fg(Color::Default);
grid[(mid, i)].set_bg(Color::Default);
grid[(mid, i)]
.set_fg(theme_default.fg)
.set_bg(theme_default.bg);
//set_and_join_box(grid, (mid + 80, i), VERT_BOUNDARY);
grid[(mid + 80, i)].set_fg(Color::Default);
grid[(mid + 80, i)].set_bg(Color::Default);
grid[(mid + 80, i)]
.set_fg(theme_default.fg)
.set_bg(theme_default.bg);
}
}
mid
@ -425,7 +429,7 @@ impl Component for Composer {
),
None,
);
clear_area(grid, ((x, y), (set_y(bottom_right, y))));
clear_area(grid, ((x, y), (set_y(bottom_right, y))), theme_default);
change_colors(
grid,
(
@ -442,6 +446,7 @@ impl Component for Composer {
pos_dec(upper_left, (0, 1)),
set_x(bottom_right, get_x(upper_left) + mid),
),
theme_default,
);
clear_area(
grid,
@ -452,6 +457,7 @@ impl Component for Composer {
),
bottom_right,
),
theme_default,
);
}
@ -462,7 +468,7 @@ impl Component for Composer {
match embed_pty {
EmbedStatus::Running(_, _) => {
let mut guard = embed_pty.lock().unwrap();
clear_area(grid, embed_area);
clear_area(grid, embed_area, theme_default);
copy_area(
grid,
&guard.grid,
@ -475,13 +481,13 @@ impl Component for Composer {
return;
}
EmbedStatus::Stopped(_, _) => {
clear_area(grid, body_area);
clear_area(grid, body_area, theme_default);
write_string_to_grid(
"process has stopped, press 'e' to re-activate",
grid,
Color::Default,
Color::Default,
Attr::Default,
theme_default.fg,
theme_default.bg,
theme_default.attrs,
body_area,
None,
);
@ -501,7 +507,7 @@ impl Component for Composer {
set_y(upper_left!(body_area), get_y(bottom_right!(body_area))),
bottom_right!(body_area),
),
Color::Default,
theme_default.fg,
Color::Byte(237),
);
} else {
@ -511,8 +517,8 @@ impl Component for Composer {
set_y(upper_left!(body_area), get_y(bottom_right!(body_area))),
bottom_right!(body_area),
),
Color::Default,
Color::Default,
theme_default.fg,
theme_default.bg,
);
}

View File

@ -366,13 +366,13 @@ impl Component for Listing {
if right_component_width == total_cols {
if let Err(err) = context.is_online(self.cursor_pos.0) {
clear_area(grid, area);
clear_area(grid, area, self.theme_default);
let (x, _) = write_string_to_grid(
"offline: ",
grid,
Color::Byte(243),
Color::Default,
Attr::Default,
self.theme_default.bg,
self.theme_default.attrs,
(set_x(upper_left, mid + 1), bottom_right),
None,
);
@ -380,8 +380,8 @@ impl Component for Listing {
&err.to_string(),
grid,
Color::Red,
Color::Default,
Attr::Default,
self.theme_default.bg,
self.theme_default.attrs,
(set_x(upper_left, x + 1), bottom_right),
None,
);
@ -395,13 +395,17 @@ impl Component for Listing {
} else {
self.draw_menu(grid, (upper_left, (mid, get_y(bottom_right))), context);
if let Err(err) = context.is_online(self.cursor_pos.0) {
clear_area(grid, (set_x(upper_left, mid + 1), bottom_right));
clear_area(
grid,
(set_x(upper_left, mid + 1), bottom_right),
self.theme_default,
);
let (x, _) = write_string_to_grid(
"offline: ",
grid,
Color::Byte(243),
Color::Default,
Attr::Default,
self.theme_default.bg,
self.theme_default.attrs,
(set_x(upper_left, mid + 1), bottom_right),
None,
);
@ -409,8 +413,8 @@ impl Component for Listing {
&err.to_string(),
grid,
Color::Red,
Color::Default,
Attr::Default,
self.theme_default.bg,
self.theme_default.attrs,
(set_x(upper_left, x + 1), bottom_right),
None,
);
@ -1069,8 +1073,8 @@ impl Listing {
"offline",
grid,
Color::Byte(243),
Color::Default,
Attr::Default,
self.theme_default.bg,
self.theme_default.attrs,
(pos_inc(upper_left, (0, 1)), bottom_right),
None,
);

View File

@ -133,6 +133,7 @@ impl MailListingTrait for CompactListing {
selected: crate::conf::value(context, "mail.listing.compact.selected"),
attachment_flag: crate::conf::value(context, "mail.listing.attachment_flag"),
thread_snooze_flag: crate::conf::value(context, "mail.listing.thread_snooze_flag"),
theme_default: crate::conf::value(context, "theme_default"),
..self.color_cache
};
if std::env::var("NO_COLOR").is_ok()
@ -147,17 +148,24 @@ impl MailListingTrait for CompactListing {
match context.accounts[self.cursor_pos.0].status(self.folder_hash) {
Ok(()) => {}
Err(_) => {
let default_cell = {
let mut ret = Cell::with_char(' ');
ret.set_fg(self.color_cache.theme_default.fg)
.set_bg(self.color_cache.theme_default.bg)
.set_attrs(self.color_cache.theme_default.attrs);
ret
};
let message: String =
context.accounts[self.cursor_pos.0][self.folder_hash].to_string();
self.data_columns.columns[0] =
CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
CellBuffer::new_with_context(message.len(), 1, default_cell, context);
self.length = 0;
write_string_to_grid(
message.as_str(),
&mut self.data_columns.columns[0],
Color::Default,
Color::Default,
Attr::Default,
self.color_cache.theme_default.fg,
self.color_cache.theme_default.bg,
self.color_cache.theme_default.attrs,
((0, 0), (MAX_COLS - 1, 0)),
None,
);
@ -283,7 +291,7 @@ impl ListingTrait for CompactListing {
let upper_left = upper_left!(area);
let bottom_right = bottom_right!(area);
if self.length == 0 {
clear_area(grid, area);
clear_area(grid, area, self.color_cache.theme_default);
copy_area(
grid,
&self.data_columns.columns[0],
@ -417,7 +425,7 @@ impl ListingTrait for CompactListing {
);
}
}
clear_area(grid, area);
clear_area(grid, area, self.color_cache.theme_default);
/* Page_no has changed, so draw new page */
let mut x = get_x(upper_left);
let mut flag_x = 0;
@ -510,6 +518,7 @@ impl ListingTrait for CompactListing {
pos_inc(upper_left, (0, self.length - top_idx)),
bottom_right,
),
self.color_cache.theme_default,
);
}
context.dirty_areas.push_back(area);
@ -563,8 +572,15 @@ impl ListingTrait for CompactListing {
self.new_cursor_pos.2 =
std::cmp::min(self.filtered_selection.len() - 1, self.cursor_pos.2);
} else {
let default_cell = {
let mut ret = Cell::with_char(' ');
ret.set_fg(self.color_cache.theme_default.fg)
.set_bg(self.color_cache.theme_default.bg)
.set_attrs(self.color_cache.theme_default.attrs);
ret
};
self.data_columns.columns[0] =
CellBuffer::new_with_context(0, 0, Cell::with_char(' '), context);
CellBuffer::new_with_context(0, 0, default_cell, context);
}
self.redraw_list(
context,
@ -583,8 +599,15 @@ impl ListingTrait for CompactListing {
format!("Failed to search for term {}: {}", &self.filter_term, e),
ERROR,
);
let default_cell = {
let mut ret = Cell::with_char(' ');
ret.set_fg(self.color_cache.theme_default.fg)
.set_bg(self.color_cache.theme_default.bg)
.set_attrs(self.color_cache.theme_default.attrs);
ret
};
self.data_columns.columns[0] =
CellBuffer::new_with_context(message.len(), 1, Cell::with_char(' '), context);
CellBuffer::new_with_context(message.len(), 1, default_cell, context);
write_string_to_grid(
&message,
&mut self.data_columns.columns[0],
@ -808,23 +831,30 @@ impl CompactListing {
min_width.0 = self.length.saturating_sub(1).to_string().len();
let default_cell = {
let mut ret = Cell::with_char(' ');
ret.set_fg(self.color_cache.theme_default.fg)
.set_bg(self.color_cache.theme_default.bg)
.set_attrs(self.color_cache.theme_default.attrs);
ret
};
/* index column */
self.data_columns.columns[0] =
CellBuffer::new_with_context(min_width.0, rows.len(), Cell::with_char(' '), context);
CellBuffer::new_with_context(min_width.0, rows.len(), default_cell, context);
/* date column */
self.data_columns.columns[1] =
CellBuffer::new_with_context(min_width.1, rows.len(), Cell::with_char(' '), context);
CellBuffer::new_with_context(min_width.1, rows.len(), default_cell, context);
/* from column */
self.data_columns.columns[2] =
CellBuffer::new_with_context(min_width.2, rows.len(), Cell::with_char(' '), context);
CellBuffer::new_with_context(min_width.2, rows.len(), default_cell, context);
self.data_columns.segment_tree[2] = row_widths.2.into();
/* flags column */
self.data_columns.columns[3] =
CellBuffer::new_with_context(min_width.3, rows.len(), Cell::with_char(' '), context);
CellBuffer::new_with_context(min_width.3, rows.len(), default_cell, context);
/* subject column */
self.data_columns.columns[4] =
CellBuffer::new_with_context(min_width.4, rows.len(), Cell::with_char(' '), context);
CellBuffer::new_with_context(min_width.4, rows.len(), default_cell, context);
self.data_columns.segment_tree[4] = row_widths.4.into();
for ((idx, (thread, root_env_hash)), strings) in rows {
@ -955,18 +985,14 @@ impl CompactListing {
if self.length == 0 && self.filter_term.is_empty() {
let mailbox = &account[self.cursor_pos.1];
let message = mailbox.to_string();
self.data_columns.columns[0] = CellBuffer::new_with_context(
message.len(),
self.length + 1,
Cell::with_char(' '),
context,
);
self.data_columns.columns[0] =
CellBuffer::new_with_context(message.len(), self.length + 1, default_cell, context);
write_string_to_grid(
&message,
&mut self.data_columns.columns[0],
Color::Default,
Color::Default,
Attr::Default,
self.color_cache.theme_default.fg,
self.color_cache.theme_default.bg,
self.color_cache.theme_default.attrs,
((0, 0), (MAX_COLS - 1, 0)),
None,
);
@ -1149,7 +1175,18 @@ impl Component for CompactListing {
area,
Some(get_x(upper_left)),
);
clear_area(grid, ((x, y), set_y(bottom_right, y)));
let default_cell = {
let mut ret = Cell::with_char(' ');
ret.set_fg(self.color_cache.theme_default.fg)
.set_bg(self.color_cache.theme_default.bg)
.set_attrs(self.color_cache.theme_default.attrs);
ret
};
for row in grid.bounds_iter(((x, y), set_y(bottom_right, y))) {
for c in row {
grid[c] = default_cell;
}
}
context
.dirty_areas
.push_back((upper_left, set_y(bottom_right, y + 1)));
@ -1187,7 +1224,7 @@ impl Component for CompactListing {
}
} else {
if self.length == 0 && self.dirty {
clear_area(grid, area);
clear_area(grid, area, self.color_cache.theme_default);
context.dirty_areas.push_back(area);
return;
}

View File

@ -284,7 +284,7 @@ impl ListingTrait for ConversationsListing {
let upper_left = upper_left!(area);
let bottom_right = bottom_right!(area);
if self.length == 0 {
clear_area(grid, area);
clear_area(grid, area, self.color_cache.theme_default);
copy_area(
grid,
&self.content,
@ -364,7 +364,7 @@ impl ListingTrait for ConversationsListing {
self.cursor_pos.2 = self.new_cursor_pos.2;
}
clear_area(grid, area);
clear_area(grid, area, self.color_cache.theme_default);
/* Page_no has changed, so draw new page */
copy_area(
grid,
@ -404,6 +404,7 @@ impl ListingTrait for ConversationsListing {
pos_inc(upper_left, (0, 3 * (self.length - top_idx))),
bottom_right,
),
self.color_cache.theme_default,
);
(0, self.length - top_idx)
} else {
@ -1054,6 +1055,7 @@ impl Component for ConversationsListing {
pos_inc(upper_left, (width!(area) / 3, 0)),
set_x(bottom_right, get_x(upper_left) + width!(area) / 3 + 1),
),
self.color_cache.theme_default,
);
context.dirty_areas.push_back((
pos_inc(upper_left, (width!(area) / 3, 0)),
@ -1084,7 +1086,11 @@ impl Component for ConversationsListing {
for c in grid.row_iter(x..(get_x(bottom_right) + 1), y) {
grid[c] = Cell::default();
}
clear_area(grid, ((x, y), set_y(bottom_right, y)));
clear_area(
grid,
((x, y), set_y(bottom_right, y)),
self.color_cache.theme_default,
);
context
.dirty_areas
.push_back((upper_left, set_y(bottom_right, y + 1)));
@ -1125,7 +1131,7 @@ impl Component for ConversationsListing {
}
if self.unfocused {
if self.length == 0 && self.dirty {
clear_area(grid, area);
clear_area(grid, area, self.color_cache.theme_default);
context.dirty_areas.push_back(area);
return;
}

View File

@ -191,7 +191,7 @@ impl MailListingTrait for PlainListing {
if !force && old_cursor_pos == self.new_cursor_pos {
self.view.update(temp);
} else if self.unfocused {
self.view = MailView::new(temp, None, None);
self.view = MailView::new(temp, None, None, context);
}
}
}
@ -289,7 +289,7 @@ impl ListingTrait for PlainListing {
let upper_left = upper_left!(area);
let bottom_right = bottom_right!(area);
if self.length == 0 {
clear_area(grid, area);
clear_area(grid, area, self.color_cache.theme_default);
copy_area(
grid,
&self.data_columns.columns[0],
@ -405,7 +405,7 @@ impl ListingTrait for PlainListing {
self.data_columns.widths[2] = min_col_width;
}
}
clear_area(grid, area);
clear_area(grid, area, self.color_cache.theme_default);
/* Page_no has changed, so draw new page */
let mut x = get_x(upper_left);
let mut flag_x = 0;
@ -493,6 +493,7 @@ impl ListingTrait for PlainListing {
pos_inc(upper_left, (0, self.length - top_idx)),
bottom_right,
),
self.color_cache.theme_default,
);
}
context.dirty_areas.push_back(area);
@ -995,7 +996,11 @@ impl Component for PlainListing {
area,
Some(get_x(upper_left)),
);
clear_area(grid, ((x, y), set_y(bottom_right, y)));
clear_area(
grid,
((x, y), set_y(bottom_right, y)),
self.color_cache.theme_default,
);
context
.dirty_areas
.push_back((upper_left, set_y(bottom_right, y + 1)));
@ -1031,7 +1036,7 @@ impl Component for PlainListing {
}
} else {
if self.length == 0 && self.dirty {
clear_area(grid, area);
clear_area(grid, area, self.color_cache.theme_default);
context.dirty_areas.push_back(area);
return;
}
@ -1054,7 +1059,7 @@ impl Component for PlainListing {
{
let env_hash = self.get_env_under_cursor(self.cursor_pos.2, context);
let temp = (self.cursor_pos.0, self.cursor_pos.1, env_hash);
self.view = MailView::new(temp, None, None);
self.view = MailView::new(temp, None, None, context);
self.unfocused = true;
self.dirty = true;
return true;

View File

@ -37,6 +37,7 @@ pub struct ThreadListing {
subsort: (SortField, SortOrder),
/// Cache current view.
content: CellBuffer,
color_cache: ColorCache,
row_updates: SmallVec<[ThreadHash; 8]>,
locations: Vec<EnvelopeHash>,
@ -219,7 +220,7 @@ impl ListingTrait for ThreadListing {
let upper_left = upper_left!(area);
let bottom_right = bottom_right!(area);
if self.length == 0 {
clear_area(grid, area);
clear_area(grid, area, self.color_cache.theme_default);
copy_area(grid, &self.content, area, ((0, 0), (MAX_COLS - 1, 0)));
context.dirty_areas.push_back(area);
return;
@ -387,6 +388,7 @@ impl ThreadListing {
sort: (Default::default(), Default::default()),
subsort: (Default::default(), Default::default()),
content,
color_cache: ColorCache::default(),
row_updates: SmallVec::new(),
locations: Vec::new(),
dirty: true,
@ -510,7 +512,7 @@ impl Component for ThreadListing {
let upper_left = upper_left!(area);
let bottom_right = bottom_right!(area);
if self.length == 0 && self.dirty {
clear_area(grid, area);
clear_area(grid, area, self.color_cache.theme_default);
context.dirty_areas.push_back(area);
}
@ -520,7 +522,7 @@ impl Component for ThreadListing {
let bottom_entity_rows = (pager_ratio * total_rows) / 100;
if bottom_entity_rows > total_rows {
clear_area(grid, area);
clear_area(grid, area, self.color_cache.theme_default);
context.dirty_areas.push_back(area);
return;
}
@ -596,7 +598,7 @@ impl Component for ThreadListing {
if let Some(ref mut v) = self.view {
v.update(coordinates);
} else {
self.view = Some(MailView::new(coordinates, None, None));
self.view = Some(MailView::new(coordinates, None, None, context));
}
self.view.as_mut().unwrap().draw(

View File

@ -131,7 +131,7 @@ impl Component for StatusPanel {
std::cmp::min(width.saturating_sub(cols), self.cursor.0),
std::cmp::min(height.saturating_sub(rows), self.cursor.1),
);
clear_area(grid, area);
clear_area(grid, area, Default::default());
copy_area(
grid,
&self.content,
@ -577,7 +577,7 @@ impl Component for AccountStatus {
std::cmp::min(width.saturating_sub(cols), self.cursor.0),
std::cmp::min(height.saturating_sub(rows), self.cursor.1),
);
clear_area(grid, area);
clear_area(grid, area, Default::default());
copy_area(
grid,
&self.content,

View File

@ -89,6 +89,7 @@ pub struct MailView {
headers_no: usize,
headers_cursor: usize,
force_draw_headers: bool,
theme_default: ThemeAttribute,
cmd_buf: String,
id: ComponentId,
@ -119,6 +120,7 @@ impl MailView {
coordinates: (usize, usize, EnvelopeHash),
pager: Option<Pager>,
subview: Option<Box<dyn Component>>,
context: &Context,
) -> Self {
MailView {
coordinates,
@ -132,6 +134,8 @@ impl MailView {
headers_cursor: 0,
force_draw_headers: false,
theme_default: crate::conf::value(context, "mail.view.body"),
cmd_buf: String::with_capacity(4),
id: ComponentId::new_v4(),
}
@ -373,7 +377,7 @@ impl Component for MailView {
let headers = crate::conf::value(context, "mail.view.headers");
if self.mode == ViewMode::Raw {
clear_area(grid, area);
clear_area(grid, area, self.theme_default);
context.dirty_areas.push_back(area);
get_y(upper_left)
} else {
@ -398,7 +402,7 @@ impl Component for MailView {
(set_y(upper_left, y), bottom_right),
Some(get_x(upper_left)),
);
clear_area(grid, ((_x, _y), (get_x(bottom_right), _y)));
clear_area(grid, ((_x, _y), (get_x(bottom_right), _y)), headers);
y = _y + 1;
} else {
skip_header_ctr -= 1;
@ -440,7 +444,11 @@ impl Component for MailView {
let mut x = get_x(upper_left);
if let Some(id) = id {
if sticky || skip_header_ctr == 0 {
clear_area(grid, (set_y(upper_left, y), set_y(bottom_right, y)));
clear_area(
grid,
(set_y(upper_left, y), set_y(bottom_right, y)),
headers,
);
let (_x, _) = write_string_to_grid(
"List-ID: ",
grid,
@ -541,7 +549,11 @@ impl Component for MailView {
}
self.force_draw_headers = false;
clear_area(grid, (set_y(upper_left, y), set_y(bottom_right, y)));
clear_area(
grid,
(set_y(upper_left, y), set_y(bottom_right, y)),
headers,
);
context
.dirty_areas
.push_back((upper_left, set_y(bottom_right, y + 3)));
@ -575,7 +587,11 @@ impl Component for MailView {
Ok(body) => body,
Err(e) => {
self.dirty = false;
clear_area(grid, (set_y(upper_left, y), bottom_right));
clear_area(
grid,
(set_y(upper_left, y), bottom_right),
self.theme_default,
);
context
.dirty_areas
.push_back((set_y(upper_left, y), bottom_right));

View File

@ -232,7 +232,7 @@ impl Component for EnvelopeView {
let envelope: &Envelope = &self.wrapper;
if self.mode == ViewMode::Raw {
clear_area(grid, area);
clear_area(grid, area, crate::conf::value(context, "theme_default"));
context.dirty_areas.push_back(area);
get_y(upper_left) - 1
} else {
@ -306,7 +306,11 @@ impl Component for EnvelopeView {
grid[(x, y)].set_bg(Color::Default);
grid[(x, y)].set_fg(Color::Default);
}
clear_area(grid, (set_y(upper_left, y + 1), set_y(bottom_right, y + 2)));
clear_area(
grid,
(set_y(upper_left, y + 1), set_y(bottom_right, y + 2)),
crate::conf::value(context, "theme_default"),
);
context
.dirty_areas
.push_back((upper_left, set_y(bottom_right, y + 1)));

View File

@ -500,7 +500,7 @@ impl ThreadView {
if self.dirty || (page_no != prev_page_no) {
if page_no != prev_page_no {
clear_area(grid, area);
clear_area(grid, area, crate::conf::value(context, "theme_default"));
}
let visibles: Vec<&usize> = self
.visible_entries
@ -567,6 +567,7 @@ impl ThreadView {
upper_left!(area),
set_x(bottom_right, get_x(upper_left!(area)) + 1),
),
context,
self.cursor_pos,
rows,
visibles.len(),
@ -620,6 +621,7 @@ impl ThreadView {
upper_left!(area),
set_x(bottom_right, get_x(upper_left!(area)) + 1),
),
context,
self.cursor_pos,
rows,
visibles.len(),
@ -684,7 +686,11 @@ impl ThreadView {
context
.dirty_areas
.push_back(((mid, y + 1), set_x(bottom_right, mid)));
clear_area(grid, ((mid, y + 1), set_x(bottom_right, mid)));
clear_area(
grid,
((mid, y + 1), set_x(bottom_right, mid)),
crate::conf::value(context, "theme_default"),
);
y + 2
} else {
get_y(upper_left) + 2
@ -711,7 +717,11 @@ impl ThreadView {
.draw(grid, (upper_left, bottom_right), context);
}
(false, true) => {
clear_area(grid, ((mid + 1, get_y(upper_left) + y - 1), bottom_right));
clear_area(
grid,
((mid + 1, get_y(upper_left) + y - 1), bottom_right),
crate::conf::value(context, "theme_default"),
);
self.draw_list(grid, (set_y(upper_left, y), bottom_right), context);
}
(_, false) => {
@ -728,7 +738,7 @@ impl ThreadView {
let bottom_entity_rows = (pager_ratio * total_rows) / 100;
if bottom_entity_rows > total_rows {
clear_area(grid, area);
clear_area(grid, area, crate::conf::value(context, "theme_default"));
context.dirty_areas.push_back(area);
return;
}
@ -793,7 +803,11 @@ impl ThreadView {
/* if this is the first ever draw, there is nothing on the grid to update so populate it
* first */
if !self.initiated {
clear_area(grid, (set_y(upper_left, y), bottom_right));
clear_area(
grid,
(set_y(upper_left, y), bottom_right),
crate::conf::value(context, "theme_default"),
);
let (width, height) = self.content.size();
match (self.show_mailview, self.show_thread) {

View File

@ -179,7 +179,7 @@ impl Component for VSplit {
(false, true) => total_cols,
(true, false) => 0,
(false, false) => {
clear_area(grid, area);
clear_area(grid, area, crate::conf::value(context, "theme_default"));
return;
}
};
@ -575,7 +575,7 @@ impl Component for Pager {
return;
}
clear_area(grid, area);
clear_area(grid, area, crate::conf::value(context, "theme_default"));
let (width, height) = self.content.size();
let (cols, rows) = (width!(area), height!(area));
self.cursor = (
@ -808,7 +808,7 @@ impl StatusBar {
}
fn draw_execute_bar(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
clear_area(grid, area);
clear_area(grid, area, crate::conf::value(context, "theme_default"));
let (x, y) = write_string_to_grid(
self.ex_buffer.as_str(),
grid,
@ -938,6 +938,7 @@ impl Component for StatusBar {
),
set_y(bottom_right, get_y(bottom_right) - height),
),
context,
self.auto_complete.cursor(),
hist_height,
self.auto_complete.suggestions().len(),
@ -984,7 +985,11 @@ impl Component for StatusBar {
} else {
self.auto_complete.cursor()
};
clear_area(grid, hist_area);
clear_area(
grid,
hist_area,
crate::conf::value(context, "theme_default"),
);
if hist_height > 0 {
change_colors(
grid,
@ -1327,11 +1332,11 @@ impl Tabbed {
let upper_left = upper_left!(area);
let bottom_right = bottom_right!(area);
let tab_bar_attribute = crate::conf::value(context, "tab.bar");
if self.children.is_empty() {
clear_area(grid, area);
clear_area(grid, area, tab_bar_attribute);
return;
}
let tab_bar_attribute = crate::conf::value(context, "tab.bar");
let tab_unfocused_attribute = crate::conf::value(context, "tab.unfocused");
let mut tab_focused_attribute = crate::conf::value(context, "tab.focused");
if std::env::var("NO_COLOR").is_ok()
@ -1423,6 +1428,7 @@ impl Component for Tabbed {
upper_left!(area),
set_x(upper_left!(area), get_x(bottom_right!(area))),
),
crate::conf::value(context, "tab.bar"),
);
context.dirty_areas.push_back((
upper_left!(area),
@ -1464,7 +1470,7 @@ impl Component for Tabbed {
),
);
context.dirty_areas.push_back(area);
clear_area(grid, area);
clear_area(grid, area, crate::conf::value(context, "theme_default"));
create_box(grid, area);
let area = (
pos_inc(upper_left!(area), (3, 2)),
@ -2327,14 +2333,13 @@ impl fmt::Display for RawBuffer {
impl Component for RawBuffer {
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
if self.dirty {
clear_area(grid, area);
let (width, height) = self.buf.size();
let (cols, rows) = (width!(area), height!(area));
self.cursor = (
std::cmp::min(width.saturating_sub(cols), self.cursor.0),
std::cmp::min(height.saturating_sub(rows), self.cursor.1),
);
clear_area(grid, area);
clear_area(grid, area, crate::conf::value(context, "theme_default"));
copy_area(
grid,
&self.buf,

View File

@ -388,15 +388,16 @@ impl Component for FormWidget {
let bottom_right = bottom_right!(area);
if self.dirty {
let label_attrs = crate::conf::value(context, "widgets.form.label");
clear_area(
grid,
(
upper_left,
set_y(bottom_right, get_y(upper_left) + self.layout.len()),
),
label_attrs,
);
let label_attrs = crate::conf::value(context, "widgets.form.label");
for (i, k) in self.layout.iter().enumerate() {
let v = self.fields.get_mut(k).unwrap();
/* Write field label */
@ -472,6 +473,7 @@ impl Component for FormWidget {
pos_inc(upper_left, (0, length)),
set_y(bottom_right, length + 2 + get_y(upper_left)),
),
label_attrs,
);
if !self.hide_buttons {
self.buttons.draw(
@ -489,6 +491,7 @@ impl Component for FormWidget {
set_y(upper_left, length + 4 + get_y(upper_left)),
bottom_right,
),
label_attrs,
);
self.dirty = false;
}
@ -642,9 +645,9 @@ impl<T> Component for ButtonWidget<T>
where
T: std::fmt::Debug + Default + Send,
{
fn draw(&mut self, grid: &mut CellBuffer, area: Area, _context: &mut Context) {
fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) {
if self.dirty {
clear_area(grid, area);
clear_area(grid, area, crate::conf::value(context, "theme_default"));
let upper_left = upper_left!(area);
let mut len = 0;
@ -927,6 +930,7 @@ impl ScrollBar {
self,
grid: &mut CellBuffer,
area: Area,
context: &Context,
pos: usize,
visible_rows: usize,
length: usize,
@ -941,7 +945,7 @@ impl ScrollBar {
if self.show_arrows {
height -= height;
}
clear_area(grid, area);
clear_area(grid, area, crate::conf::value(context, "theme_default"));
let visible_ratio: f32 = (std::cmp::min(visible_rows, length) as f32) / (length as f32);
let scrollbar_height = std::cmp::max((visible_ratio * (height as f32)) as usize, 1);

View File

@ -1595,10 +1595,13 @@ pub fn copy_area(grid_dest: &mut CellBuffer, grid_src: &CellBuffer, dest: Area,
src_x = get_x(upper_left!(src));
src_y += 1;
if src_y > get_y(bottom_right!(src)) {
clear_area(
grid_dest,
((get_x(upper_left!(dest)), y + 1), bottom_right!(dest)),
);
for row in
grid_dest.bounds_iter(((get_x(upper_left!(dest)), y + 1), bottom_right!(dest)))
{
for c in row {
grid_dest[c].set_ch(' ');
}
}
ret.1 = y;
break;
}
@ -1747,13 +1750,17 @@ pub fn write_string_to_grid(
}
/// Completely clear an `Area` with an empty char and the terminal's default colors.
pub fn clear_area(grid: &mut CellBuffer, area: Area) {
pub fn clear_area(grid: &mut CellBuffer, area: Area, attributes: crate::conf::ThemeAttribute) {
if !is_valid_area!(area) {
return;
}
for row in grid.bounds_iter(area) {
for c in row {
grid[c] = Cell::default();
grid[c]
.set_fg(attributes.fg)
.set_bg(attributes.bg)
.set_attrs(attributes.attrs);
}
}
}
@ -2364,21 +2371,13 @@ pub mod boundaries {
if !grid.ascii_drawing {
for x in get_x(upper_left)..get_x(bottom_right) {
grid[(x, get_y(upper_left))]
.set_ch(HORZ_BOUNDARY)
.set_fg(Color::Byte(240));
grid[(x, get_y(bottom_right))]
.set_ch(HORZ_BOUNDARY)
.set_fg(Color::Byte(240));
grid[(x, get_y(upper_left))].set_ch(HORZ_BOUNDARY);
grid[(x, get_y(bottom_right))].set_ch(HORZ_BOUNDARY);
}
for y in get_y(upper_left)..get_y(bottom_right) {
grid[(get_x(upper_left), y)]
.set_ch(VERT_BOUNDARY)
.set_fg(Color::Byte(240));
grid[(get_x(bottom_right), y)]
.set_ch(VERT_BOUNDARY)
.set_fg(Color::Byte(240));
grid[(get_x(upper_left), y)].set_ch(VERT_BOUNDARY);
grid[(get_x(bottom_right), y)].set_ch(VERT_BOUNDARY);
}
set_and_join_box(grid, upper_left, BoxBoundary::Horizontal);
set_and_join_box(

View File

@ -483,6 +483,7 @@ impl EmbedGrid {
terminal_size.1.saturating_sub(1),
),
),
Default::default(),
);
debug!("{}", EscCode::from((&(*state), byte)));
*state = State::Normal;
@ -565,7 +566,11 @@ impl EmbedGrid {
}
}
debug!("{}", EscCode::from((&(*state), byte)));
clear_area(grid, ((0, 0), pos_dec(*terminal_size, (1, 1))));
clear_area(
grid,
((0, 0), pos_dec(*terminal_size, (1, 1))),
Default::default(),
);
*state = State::Normal;
}
(b'J', State::Csi1(ref buf)) if buf == b"0" => {
@ -586,6 +591,7 @@ impl EmbedGrid {
terminal_size.1.saturating_sub(1),
),
),
Default::default(),
);
debug!("{}", EscCode::from((&(*state), byte)));
*state = State::Normal;
@ -602,6 +608,7 @@ impl EmbedGrid {
cursor.1.saturating_sub(1) + scroll_region.top,
),
),
Default::default(),
);
debug!("{}", EscCode::from((&(*state), byte)));
*state = State::Normal;
@ -609,7 +616,11 @@ impl EmbedGrid {
(b'J', State::Csi1(ref buf)) if buf == b"2" => {
/* Erase in Display (ED), VT100.*/
/* Erase All */
clear_area(grid, ((0, 0), pos_dec(*terminal_size, (1, 1))));
clear_area(
grid,
((0, 0), pos_dec(*terminal_size, (1, 1))),
Default::default(),
);
debug!("{}", EscCode::from((&(*state), byte)));
*state = State::Normal;
}