mirror of
https://git.meli.delivery/meli/meli
synced 2024-11-19 03:25:38 +00:00
state: cull redraws of floating notifications
Cull redraws by keeping track of whether the floating box has been initialised and whether its area has been drawn over by other dirty areas.
This commit is contained in:
parent
4c1a9b2485
commit
393c5d0d53
190
src/state.rs
190
src/state.rs
@ -190,7 +190,10 @@ pub struct State {
|
||||
display_messages: SmallVec<[DisplayMessage; 8]>,
|
||||
display_messages_expiration_start: Option<UnixTimestamp>,
|
||||
display_messages_active: bool,
|
||||
display_messages_dirty: bool,
|
||||
display_messages_initialised: bool,
|
||||
display_messages_pos: usize,
|
||||
display_messages_area: Area,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -335,7 +338,9 @@ impl State {
|
||||
display_messages_expiration_start: None,
|
||||
display_messages_pos: 0,
|
||||
display_messages_active: false,
|
||||
|
||||
display_messages_dirty: false,
|
||||
display_messages_initialised: false,
|
||||
display_messages_area: ((0, 0), (0, 0)),
|
||||
context: Context {
|
||||
accounts,
|
||||
settings: settings.clone(),
|
||||
@ -522,6 +527,9 @@ impl State {
|
||||
.resize(self.cols, self.rows, Cell::with_char(' '));
|
||||
|
||||
self.rcv_event(UIEvent::Resize);
|
||||
self.display_messages_dirty = true;
|
||||
self.display_messages_initialised = false;
|
||||
self.display_messages_area = ((0, 0), (0, 0));
|
||||
|
||||
// Invalidate dirty areas.
|
||||
self.context.dirty_areas.clear();
|
||||
@ -546,6 +554,8 @@ impl State {
|
||||
.unwrap_or(false)
|
||||
{
|
||||
self.display_messages_active = false;
|
||||
self.display_messages_dirty = true;
|
||||
self.display_messages_initialised = false;
|
||||
self.display_messages_expiration_start = None;
|
||||
areas.push((
|
||||
(0, 0),
|
||||
@ -556,6 +566,18 @@ impl State {
|
||||
|
||||
/* Sort by x_start, ie upper_left corner's x coordinate */
|
||||
areas.sort_by(|a, b| (a.0).0.partial_cmp(&(b.0).0).unwrap());
|
||||
|
||||
if self.display_messages_active {
|
||||
/* Check if any dirty area intersects with the area occupied by floating notification
|
||||
* box */
|
||||
let (displ_top, displ_bot) = self.display_messages_area;
|
||||
for &((top_x, top_y), (bottom_x, bottom_y)) in &areas {
|
||||
self.display_messages_dirty |= !(bottom_y < displ_top.1
|
||||
|| displ_bot.1 < top_y
|
||||
|| bottom_x < displ_top.0
|
||||
|| displ_bot.0 < top_x);
|
||||
}
|
||||
}
|
||||
/* draw each dirty area */
|
||||
let rows = self.rows;
|
||||
for y in 0..rows {
|
||||
@ -613,87 +635,119 @@ impl State {
|
||||
}
|
||||
}
|
||||
|
||||
if self.display_messages_active {
|
||||
if self.display_messages_dirty && self.display_messages_active {
|
||||
if let Some(DisplayMessage {
|
||||
ref timestamp,
|
||||
ref msg,
|
||||
..
|
||||
}) = self.display_messages.get(self.display_messages_pos)
|
||||
{
|
||||
let noto_colors = crate::conf::value(&self.context, "status.notification");
|
||||
use crate::melib::text_processing::{Reflow, TextProcessing};
|
||||
|
||||
let msg_lines = msg.split_lines_reflow(Reflow::All, Some(self.cols / 3));
|
||||
let width = msg_lines
|
||||
.iter()
|
||||
.map(|line| line.grapheme_len() + 4)
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
|
||||
let displ_area = place_in_area(
|
||||
(
|
||||
(0, 0),
|
||||
(self.cols.saturating_sub(1), self.rows.saturating_sub(1)),
|
||||
),
|
||||
(width, std::cmp::min(self.rows, msg_lines.len() + 4)),
|
||||
false,
|
||||
false,
|
||||
);
|
||||
for row in self.overlay_grid.bounds_iter(displ_area) {
|
||||
for c in row {
|
||||
self.overlay_grid[c]
|
||||
.set_ch(' ')
|
||||
.set_fg(noto_colors.fg)
|
||||
.set_bg(noto_colors.bg)
|
||||
.set_attrs(noto_colors.attrs);
|
||||
if !self.display_messages_initialised {
|
||||
{
|
||||
/* Clear area previously occupied by floating notification box */
|
||||
let displ_area = self.display_messages_area;
|
||||
for y in get_y(upper_left!(displ_area))..=get_y(bottom_right!(displ_area)) {
|
||||
(self.draw_horizontal_segment_fn)(
|
||||
&mut self.grid,
|
||||
self.stdout.as_mut().unwrap(),
|
||||
get_x(upper_left!(displ_area)),
|
||||
get_x(bottom_right!(displ_area)),
|
||||
y,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
let ((x, mut y), box_displ_area_bottom_right) =
|
||||
create_box(&mut self.overlay_grid, displ_area);
|
||||
for line in msg_lines
|
||||
.into_iter()
|
||||
.chain(Some(String::new()))
|
||||
.chain(Some(melib::datetime::timestamp_to_string(*timestamp, None)))
|
||||
{
|
||||
write_string_to_grid(
|
||||
&line,
|
||||
&mut self.overlay_grid,
|
||||
noto_colors.fg,
|
||||
noto_colors.bg,
|
||||
noto_colors.attrs,
|
||||
((x, y), box_displ_area_bottom_right),
|
||||
Some(x),
|
||||
);
|
||||
y += 1;
|
||||
}
|
||||
let noto_colors = crate::conf::value(&self.context, "status.notification");
|
||||
use crate::melib::text_processing::{Reflow, TextProcessing};
|
||||
|
||||
if self.display_messages.len() > 1 {
|
||||
write_string_to_grid(
|
||||
if self.display_messages_pos == 0 {
|
||||
"Next: >"
|
||||
} else if self.display_messages_pos + 1 == self.display_messages.len() {
|
||||
"Prev: <"
|
||||
} else {
|
||||
"Prev: <, Next: >"
|
||||
},
|
||||
&mut self.overlay_grid,
|
||||
noto_colors.fg,
|
||||
noto_colors.bg,
|
||||
noto_colors.attrs,
|
||||
((x, y), box_displ_area_bottom_right),
|
||||
Some(x),
|
||||
let msg_lines = msg.split_lines_reflow(Reflow::All, Some(self.cols / 3));
|
||||
let width = msg_lines
|
||||
.iter()
|
||||
.map(|line| line.grapheme_len() + 4)
|
||||
.max()
|
||||
.unwrap_or(0);
|
||||
|
||||
let displ_area = place_in_area(
|
||||
(
|
||||
(0, 0),
|
||||
(self.cols.saturating_sub(1), self.rows.saturating_sub(1)),
|
||||
),
|
||||
(width, std::cmp::min(self.rows, msg_lines.len() + 4)),
|
||||
false,
|
||||
false,
|
||||
);
|
||||
for row in self.overlay_grid.bounds_iter(displ_area) {
|
||||
for c in row {
|
||||
self.overlay_grid[c]
|
||||
.set_ch(' ')
|
||||
.set_fg(noto_colors.fg)
|
||||
.set_bg(noto_colors.bg)
|
||||
.set_attrs(noto_colors.attrs);
|
||||
}
|
||||
}
|
||||
let ((x, mut y), box_displ_area_bottom_right) =
|
||||
create_box(&mut self.overlay_grid, displ_area);
|
||||
for line in msg_lines
|
||||
.into_iter()
|
||||
.chain(Some(String::new()))
|
||||
.chain(Some(melib::datetime::timestamp_to_string(*timestamp, None)))
|
||||
{
|
||||
write_string_to_grid(
|
||||
&line,
|
||||
&mut self.overlay_grid,
|
||||
noto_colors.fg,
|
||||
noto_colors.bg,
|
||||
noto_colors.attrs,
|
||||
((x, y), box_displ_area_bottom_right),
|
||||
Some(x),
|
||||
);
|
||||
y += 1;
|
||||
}
|
||||
|
||||
if self.display_messages.len() > 1 {
|
||||
write_string_to_grid(
|
||||
if self.display_messages_pos == 0 {
|
||||
"Next: >"
|
||||
} else if self.display_messages_pos + 1 == self.display_messages.len() {
|
||||
"Prev: <"
|
||||
} else {
|
||||
"Prev: <, Next: >"
|
||||
},
|
||||
&mut self.overlay_grid,
|
||||
noto_colors.fg,
|
||||
noto_colors.bg,
|
||||
noto_colors.attrs,
|
||||
((x, y), box_displ_area_bottom_right),
|
||||
Some(x),
|
||||
);
|
||||
}
|
||||
self.display_messages_area = displ_area;
|
||||
}
|
||||
for y in get_y(upper_left!(displ_area))..=get_y(bottom_right!(displ_area)) {
|
||||
for y in get_y(upper_left!(self.display_messages_area))
|
||||
..=get_y(bottom_right!(self.display_messages_area))
|
||||
{
|
||||
(self.draw_horizontal_segment_fn)(
|
||||
&mut self.overlay_grid,
|
||||
self.stdout.as_mut().unwrap(),
|
||||
get_x(upper_left!(displ_area)),
|
||||
get_x(bottom_right!(displ_area)),
|
||||
get_x(upper_left!(self.display_messages_area)),
|
||||
get_x(bottom_right!(self.display_messages_area)),
|
||||
y,
|
||||
);
|
||||
}
|
||||
}
|
||||
self.display_messages_dirty = false;
|
||||
} else if self.display_messages_dirty {
|
||||
/* Clear area previously occupied by floating notification box */
|
||||
let displ_area = self.display_messages_area;
|
||||
for y in get_y(upper_left!(displ_area))..=get_y(bottom_right!(displ_area)) {
|
||||
(self.draw_horizontal_segment_fn)(
|
||||
&mut self.grid,
|
||||
self.stdout.as_mut().unwrap(),
|
||||
get_x(upper_left!(displ_area)),
|
||||
get_x(bottom_right!(displ_area)),
|
||||
y,
|
||||
);
|
||||
}
|
||||
self.display_messages_dirty = false;
|
||||
}
|
||||
if !self.overlay.is_empty() {
|
||||
let area = center_area(
|
||||
@ -1092,12 +1146,16 @@ impl State {
|
||||
UIEvent::Input(Key::Alt('<')) => {
|
||||
self.display_messages_expiration_start = Some(melib::datetime::now());
|
||||
self.display_messages_active = true;
|
||||
self.display_messages_initialised = false;
|
||||
self.display_messages_dirty = true;
|
||||
self.display_messages_pos = self.display_messages_pos.saturating_sub(1);
|
||||
return;
|
||||
}
|
||||
UIEvent::Input(Key::Alt('>')) => {
|
||||
self.display_messages_expiration_start = Some(melib::datetime::now());
|
||||
self.display_messages_active = true;
|
||||
self.display_messages_initialised = false;
|
||||
self.display_messages_dirty = true;
|
||||
self.display_messages_pos = std::cmp::min(
|
||||
self.display_messages.len().saturating_sub(1),
|
||||
self.display_messages_pos + 1,
|
||||
@ -1110,6 +1168,8 @@ impl State {
|
||||
msg: msg.clone(),
|
||||
});
|
||||
self.display_messages_active = true;
|
||||
self.display_messages_initialised = false;
|
||||
self.display_messages_dirty = true;
|
||||
self.display_messages_expiration_start = None;
|
||||
self.display_messages_pos = self.display_messages.len() - 1;
|
||||
self.redraw();
|
||||
|
Loading…
Reference in New Issue
Block a user