ratatui_toolkit/primitives/tree_view/tree_view_ref/traits/
stateful_widget.rs

1//! StatefulWidget implementation for TreeViewRef.
2
3use ratatui::{
4    buffer::Buffer,
5    layout::Rect,
6    widgets::{StatefulWidget, Widget},
7};
8
9use crate::primitives::tree_view::tree_view_ref::TreeViewRef;
10use crate::primitives::tree_view::tree_view_state::TreeViewState;
11
12impl<'a, 'b, T> StatefulWidget for TreeViewRef<'a, 'b, T> {
13    type State = TreeViewState;
14
15    fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
16        let area = match self.block {
17            Some(ref b) => {
18                let inner = b.inner(area);
19                b.clone().render(area, buf);
20                inner
21            }
22            None => area,
23        };
24
25        if area.height == 0 {
26            return;
27        }
28
29        let items = self.flatten_tree(state);
30        let visible_height = area.height as usize;
31
32        // Adjust scroll offset to ensure selected item is visible
33        if let Some(ref selected) = state.selected_path {
34            if let Some(selected_idx) = items.iter().position(|(_, path)| path == selected) {
35                if selected_idx < state.offset {
36                    state.offset = selected_idx;
37                } else if selected_idx >= state.offset + visible_height {
38                    state.offset = selected_idx.saturating_sub(visible_height - 1);
39                }
40            }
41        }
42
43        // Render visible items
44        for (i, (line, path)) in items
45            .iter()
46            .skip(state.offset)
47            .take(visible_height)
48            .enumerate()
49        {
50            let y = area.y + i as u16;
51
52            // Fill background for selected row (full-width highlight like Yazi)
53            let is_selected = state.selected_path.as_ref() == Some(path);
54            if is_selected && self.highlight_style.is_some() {
55                let style = self.highlight_style.unwrap();
56                for x in area.x..(area.x + area.width) {
57                    buf[(x, y)].set_style(style);
58                }
59            }
60
61            buf.set_line(area.x, y, line, area.width);
62        }
63    }
64}