agent_core/tui/layout/
minimal.rs1use ratatui::layout::{Constraint, Direction, Layout};
4
5use crate::tui::widgets::widget_ids;
6
7use super::types::{LayoutContext, LayoutResult, WidgetSizes};
8
9#[derive(Clone)]
11pub struct MinimalOptions {
12 pub main_widget_id: &'static str,
14 pub input_widget_id: &'static str,
16 pub fixed_input_height: Option<u16>,
18}
19
20impl Default for MinimalOptions {
21 fn default() -> Self {
22 Self {
23 main_widget_id: widget_ids::CHAT_VIEW,
24 input_widget_id: widget_ids::TEXT_INPUT,
25 fixed_input_height: None,
26 }
27 }
28}
29
30pub fn compute(ctx: &LayoutContext, _sizes: &WidgetSizes, opts: &MinimalOptions) -> LayoutResult {
32 let mut result = LayoutResult::default();
33 let area = ctx.frame_area;
34
35 let input_height = opts.fixed_input_height.unwrap_or_else(|| {
36 if ctx.show_throbber {
37 3
38 } else {
39 (ctx.input_visual_lines as u16).max(1) + 2
40 }
41 });
42
43 let chunks = Layout::default()
44 .direction(Direction::Vertical)
45 .constraints([Constraint::Min(1), Constraint::Length(input_height)])
46 .split(area);
47
48 result.widget_areas.insert(opts.main_widget_id, chunks[0]);
49 result.widget_areas.insert(opts.input_widget_id, chunks[1]);
50 result.input_area = Some(chunks[1]);
51
52 result.render_order = vec![opts.main_widget_id, opts.input_widget_id];
53
54 result
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60 use crate::tui::themes::Theme;
61 use crate::tui::widgets::widget_ids;
62 use ratatui::layout::Rect;
63 use std::collections::{HashMap, HashSet};
64
65 fn test_context(area: Rect) -> LayoutContext<'static> {
66 static THEME: std::sync::LazyLock<Theme> = std::sync::LazyLock::new(Theme::default);
67 LayoutContext {
68 frame_area: area,
69 show_throbber: false,
70 input_visual_lines: 1,
71 theme: &THEME,
72 active_widgets: HashSet::new(),
73 }
74 }
75
76 fn test_sizes() -> WidgetSizes {
77 WidgetSizes {
78 heights: HashMap::new(),
79 is_active: HashMap::new(),
80 }
81 }
82
83 #[test]
84 fn test_minimal_layout() {
85 let area = Rect::new(0, 0, 80, 24);
86 let ctx = test_context(area);
87 let sizes = test_sizes();
88
89 let result = compute(&ctx, &sizes, &MinimalOptions::default());
90
91 assert!(result.widget_areas.contains_key(widget_ids::CHAT_VIEW));
92 assert!(result.widget_areas.contains_key(widget_ids::TEXT_INPUT));
93 assert!(!result.widget_areas.contains_key(widget_ids::STATUS_BAR));
95 }
96}