Move buffer copy to its own function, it's more readable
This commit is contained in:
@ -124,20 +124,24 @@ impl Component for Backlog {
|
|||||||
value: PrerenderValue::Rendered(buf),
|
value: PrerenderValue::Rendered(buf),
|
||||||
}) if *key == text_area.width => {
|
}) if *key == text_area.width => {
|
||||||
// We already rendered it, copy the buffer.
|
// We already rendered it, copy the buffer.
|
||||||
assert_eq!(buf.area().width, text_area.width);
|
assert_eq!(text_area.width, buf.area.width);
|
||||||
for (y, line) in buf
|
let top_padding = text_area.height.saturating_sub(buf.area.height);
|
||||||
.content()
|
let skip_top_lines = buf.area.height.saturating_sub(text_area.height);
|
||||||
.chunks(u16::min(buf.area().width, text_area.width) as usize)
|
copy_buffer(
|
||||||
.enumerate()
|
buf,
|
||||||
.skip(buf.area().height.saturating_sub(text_area.height) as usize)
|
Rect {
|
||||||
{
|
x: 0,
|
||||||
for (x, cell) in line.into_iter().enumerate() {
|
y: 0,
|
||||||
*frame.buffer_mut().get_mut(
|
width: text_area.width,
|
||||||
text_area.x + (x as u16),
|
height: buf.area.height - skip_top_lines,
|
||||||
text_area.y + text_area.height + (y as u16) - buf.area().height,
|
},
|
||||||
) = cell.clone();
|
frame.buffer_mut(),
|
||||||
}
|
Rect {
|
||||||
}
|
y: text_area.y + top_padding,
|
||||||
|
height: text_area.height - top_padding,
|
||||||
|
..text_area
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
buf.area().height
|
buf.area().height
|
||||||
},
|
},
|
||||||
@ -145,28 +149,37 @@ impl Component for Backlog {
|
|||||||
let widget = BottomAlignedParagraph::new(item.text);
|
let widget = BottomAlignedParagraph::new(item.text);
|
||||||
let height = widget.render_overlap(text_area, frame.buffer_mut());
|
let height = widget.render_overlap(text_area, frame.buffer_mut());
|
||||||
|
|
||||||
// Copy the drawn result to a buffer for caching
|
// If the whole widget fits in the text_area, copy the drawn result to a buffer
|
||||||
let mut buf = ratatui::buffer::Buffer::empty(Rect {
|
// for caching
|
||||||
x: 0,
|
if height <= text_area.height {
|
||||||
y: 0,
|
let mut buf = ratatui::buffer::Buffer::empty(Rect {
|
||||||
width: text_area.width,
|
x: 0,
|
||||||
height,
|
y: 0,
|
||||||
});
|
width: text_area.width,
|
||||||
for y in 0..height {
|
height,
|
||||||
// TODO: only copy the width actually drawn by the widget
|
});
|
||||||
for x in 0..text_area.width {
|
let top_padding = text_area.height.saturating_sub(buf.area.height);
|
||||||
*buf.get_mut(x, y) = frame
|
copy_buffer(
|
||||||
.buffer_mut()
|
frame.buffer_mut(),
|
||||||
.get(text_area.x + x, text_area.y + text_area.height + y - height)
|
Rect {
|
||||||
.clone()
|
y: text_area.y + top_padding,
|
||||||
}
|
height: text_area.height - top_padding,
|
||||||
|
..text_area
|
||||||
|
},
|
||||||
|
&mut buf,
|
||||||
|
Rect {
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: text_area.width, // TODO: only copy the width actually drawn by the widget
|
||||||
|
height: height,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
*prerender = Some(PrerenderInner {
|
||||||
|
key: text_area.width,
|
||||||
|
value: PrerenderValue::Rendered(buf),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
*prerender = Some(PrerenderInner {
|
|
||||||
key: text_area.width,
|
|
||||||
value: PrerenderValue::Rendered(buf),
|
|
||||||
});
|
|
||||||
|
|
||||||
height
|
height
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -185,3 +198,44 @@ impl Component for Backlog {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn copy_buffer(src: &Buffer, src_area: Rect, dst: &mut Buffer, dst_area: Rect) {
|
||||||
|
assert_eq!(src_area.width, dst_area.width, "width mismatch");
|
||||||
|
assert_eq!(src_area.height, dst_area.height, "height mismatch");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
src_area.x + src_area.width <= src.area.width,
|
||||||
|
"src width overflow"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
src_area.y + src_area.height <= src.area.height,
|
||||||
|
"src height overflow"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
dst_area.x + dst_area.width <= dst.area.width,
|
||||||
|
"dst width overflow"
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
dst_area.y + dst_area.height <= dst.area.height,
|
||||||
|
"dst height overflow"
|
||||||
|
);
|
||||||
|
|
||||||
|
for (y, line) in src
|
||||||
|
.content()
|
||||||
|
.chunks(src.area.width as usize)
|
||||||
|
.skip(src_area.y as usize)
|
||||||
|
.take(dst_area.height as usize)
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
for (x, cell) in line
|
||||||
|
.into_iter()
|
||||||
|
.skip(src_area.x as usize)
|
||||||
|
.take(src_area.width as usize)
|
||||||
|
.enumerate()
|
||||||
|
{
|
||||||
|
*dst.get_mut(dst_area.x + (x as u16), dst_area.y + (y as u16)) = src
|
||||||
|
.get(src_area.x + (x as u16), src_area.y + (y as u16))
|
||||||
|
.clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user