Skip to main content

codetether_agent/tui/ui/chat_view/
layout_compute.rs

1//! Layout computation for the chat view.
2//!
3//! Splits the available area into messages, input, optional suggestions,
4//! and status rectangles.
5
6use ratatui::layout::{Constraint, Direction, Layout, Rect};
7
8use super::layout_chunks::ChatChunks;
9use crate::tui::app::state::App;
10
11/// Split `area` into message/input/suggestions/status rectangles.
12///
13/// Input height adapts to lines typed (3–6 rows). Suggestions row appears
14/// only when autocomplete is visible.
15///
16/// # Examples
17///
18/// ```rust,no_run
19/// # use codetether_agent::tui::ui::chat_view::layout_compute::compute_chat_chunks;
20/// # fn d(a:&codetether_agent::tui::app::state::App){ let c = compute_chat_chunks(ratatui::layout::Rect::new(0,0,80,24), a); assert!(c.messages.width>0); }
21/// ```
22pub fn compute_chat_chunks(area: Rect, app: &App) -> ChatChunks {
23    let suggestions_visible = app.state.slash_suggestions_visible();
24    let input_lines_count = app.state.input.lines().count().max(1);
25    let input_height = (input_lines_count as u16 + 2).clamp(3, 6);
26    let status_height = status_bar_height(area.width);
27    let constraints: &[Constraint] = if suggestions_visible {
28        &[
29            Constraint::Min(8),
30            Constraint::Length(input_height),
31            Constraint::Length(5),
32            Constraint::Length(status_height),
33        ]
34    } else {
35        &[
36            Constraint::Min(8),
37            Constraint::Length(input_height),
38            Constraint::Length(status_height),
39        ]
40    };
41    let chunks = Layout::default()
42        .direction(Direction::Vertical)
43        .constraints(constraints)
44        .split(area);
45    ChatChunks {
46        messages: chunks[0],
47        input: chunks[1],
48        suggestions: suggestions_visible.then(|| chunks[2]),
49        status: chunks[if suggestions_visible { 3 } else { 2 }],
50    }
51}
52
53/// Height reserved for the bottom status bar, in rows.
54///
55/// Stacks to 3 rows when the terminal is narrower than the
56/// [`super::status::STACK_WIDTH_THRESHOLD`]; otherwise a single row.
57fn status_bar_height(width: u16) -> u16 {
58    if width >= super::status::STACK_WIDTH_THRESHOLD {
59        1
60    } else {
61        3
62    }
63}