vtcode_tui/core_tui/session/
impl_render.rs1use super::*;
2
3impl Session {
4 pub fn render(&mut self, frame: &mut Frame<'_>) {
5 let viewport = frame.area();
6 if viewport.height == 0 || viewport.width == 0 {
7 return;
8 }
9
10 if self.needs_full_clear {
12 frame.render_widget(Clear, viewport);
13 self.needs_full_clear = false;
14 }
15
16 let header_lines = self.header_lines();
18 let header_height = self.header_height_from_lines(viewport.width, &header_lines);
19 if header_height != self.header_rows {
20 self.header_rows = header_height;
21 self.recalculate_transcript_rows();
22 }
23
24 let mode = self.resolved_layout_mode(viewport);
25 let status_height = if viewport.width > 0 && !mode.show_footer() {
28 1
29 } else {
30 0
31 };
32 let inner_width = viewport.width.saturating_sub(2);
33 let desired_lines = self.desired_input_lines(inner_width);
34 let block_height = Self::input_block_height_for_lines(desired_lines);
35 let input_height = block_height.saturating_add(status_height);
36 self.apply_input_height(input_height);
37
38 let mut constraints = vec![Constraint::Length(header_height), Constraint::Min(1)];
39 constraints.push(Constraint::Length(input_height));
40
41 let segments = Layout::vertical(constraints).split(viewport);
42
43 let header_area = segments[0];
44 let main_area = segments[1];
45 let input_index = segments.len().saturating_sub(1);
46 let input_area = segments[input_index];
47
48 let _available_width = main_area.width;
49 let _horizontal_minimum = ui::INLINE_CONTENT_MIN_WIDTH + ui::INLINE_NAVIGATION_MIN_WIDTH;
50
51 let transcript_area = main_area;
52 let navigation_area = Rect::new(main_area.x, main_area.y, 0, 0); SessionWidget::new(self)
56 .header_lines(header_lines.clone())
57 .header_area(header_area)
58 .transcript_area(transcript_area)
59 .navigation_area(navigation_area) .render(viewport, frame.buffer_mut());
61
62 self.render_input(frame, input_area);
66 render::render_modal(self, frame, viewport);
67 slash::render_slash_palette(self, frame, viewport);
68 render::render_file_palette(self, frame, viewport);
69
70 if self.diff_preview.is_some() {
72 diff_preview::render_diff_preview(self, frame, viewport);
73 }
74
75 if self.mouse_selection.has_selection || self.mouse_selection.is_selecting {
77 self.mouse_selection
78 .apply_highlight(frame.buffer_mut(), viewport);
79
80 if self.mouse_selection.needs_copy() {
82 let text = self
83 .mouse_selection
84 .extract_text(frame.buffer_mut(), viewport);
85 if !text.is_empty() {
86 MouseSelectionState::copy_to_clipboard(&text);
87 }
88 self.mouse_selection.mark_copied();
89 }
90 }
91 }
92
93 #[allow(dead_code)]
94 pub(crate) fn render_message_spans(&self, index: usize) -> Vec<Span<'static>> {
95 let Some(line) = self.lines.get(index) else {
96 return vec![Span::raw(String::new())];
97 };
98 message_renderer::render_message_spans(
99 line,
100 &self.theme,
101 &self.labels,
102 |kind| self.prefix_text(kind),
103 |line| self.prefix_style(line),
104 |kind| self.text_fallback(kind),
105 )
106 }
107}