The motivation behind this PR is to make it so a `HistoryCell` is more like a `WidgetRef` that knows how to render itself into a `Rect` so that it can be backed by something other than a `Vec<Line>`. Because a `HistoryCell` is intended to appear in a scrollable list, we want to ensure the stack of cells can be scrolled one `Line` at a time even if the `HistoryCell` is not backed by a `Vec<Line>` itself. To this end, we introduce the `CellWidget` trait whose key method is: ``` fn render_window(&self, first_visible_line: usize, area: Rect, buf: &mut Buffer); ``` The `first_visible_line` param is what differs from `WidgetRef::render_ref()`, as a `CellWidget` needs to know the offset into its "full view" at which it should start rendering. The bookkeeping in `ConversationHistoryWidget` has been updated accordingly to ensure each `CellWidget` in the history is rendered appropriately.
33 lines
1.1 KiB
Rust
33 lines
1.1 KiB
Rust
use crate::cell_widget::CellWidget;
|
|
use ratatui::prelude::*;
|
|
|
|
/// A simple widget that just displays a list of `Line`s via a `Paragraph`.
|
|
/// This is the default rendering backend for most `HistoryCell` variants.
|
|
#[derive(Clone)]
|
|
pub(crate) struct TextBlock {
|
|
pub(crate) lines: Vec<Line<'static>>,
|
|
}
|
|
|
|
impl TextBlock {
|
|
pub(crate) fn new(lines: Vec<Line<'static>>) -> Self {
|
|
Self { lines }
|
|
}
|
|
}
|
|
|
|
impl CellWidget for TextBlock {
|
|
fn height(&self, width: u16) -> usize {
|
|
// Use the same wrapping configuration as ConversationHistoryWidget so
|
|
// measurement stays in sync with rendering.
|
|
ratatui::widgets::Paragraph::new(self.lines.clone())
|
|
.wrap(crate::conversation_history_widget::wrap_cfg())
|
|
.line_count(width)
|
|
}
|
|
|
|
fn render_window(&self, first_visible_line: usize, area: Rect, buf: &mut Buffer) {
|
|
ratatui::widgets::Paragraph::new(self.lines.clone())
|
|
.wrap(crate::conversation_history_widget::wrap_cfg())
|
|
.scroll((first_visible_line as u16, 0))
|
|
.render(area, buf);
|
|
}
|
|
}
|