code_mesh_tui/components/
status_bar.rs

1use ratatui::{
2    layout::Rect,
3    widgets::Paragraph,
4    style::Style,
5    text::{Line, Span},
6};
7use anyhow::Result;
8
9use crate::{
10    app::AppState,
11    renderer::Renderer,
12    theme::Theme,
13};
14
15/// Status bar component showing application information
16pub struct StatusBar {
17    theme: Box<dyn Theme + Send + Sync>,
18    mode: String,
19    file_path: Option<String>,
20    cursor_position: (u16, u16),
21    selection_info: Option<String>,
22}
23
24impl StatusBar {
25    /// Create a new status bar
26    pub fn new(theme: &dyn Theme) -> Self {
27        Self {
28            theme: Box::new(crate::theme::DefaultTheme), // Temporary
29            mode: "NORMAL".to_string(),
30            file_path: None,
31            cursor_position: (0, 0),
32            selection_info: None,
33        }
34    }
35    
36    /// Update the status bar
37    pub async fn update(&mut self, state: &AppState) -> Result<()> {
38        self.mode = match state {
39            AppState::Running => "NORMAL".to_string(),
40            AppState::Chat => "CHAT".to_string(),
41            AppState::FileViewer => "FILE".to_string(),
42            AppState::CommandPalette => "COMMAND".to_string(),
43            AppState::Dialog => "DIALOG".to_string(),
44            AppState::Help => "HELP".to_string(),
45            AppState::Quitting => "QUIT".to_string(),
46        };
47        Ok(())
48    }
49    
50    /// Set the current file path
51    pub fn set_file_path(&mut self, path: Option<String>) {
52        self.file_path = path;
53    }
54    
55    /// Set cursor position
56    pub fn set_cursor_position(&mut self, x: u16, y: u16) {
57        self.cursor_position = (x, y);
58    }
59    
60    /// Set selection information
61    pub fn set_selection_info(&mut self, info: Option<String>) {
62        self.selection_info = info;
63    }
64    
65    /// Update theme
66    pub fn update_theme(&mut self, theme: &dyn Theme) {
67        // In a real implementation, we'd clone or recreate the theme
68        // For now, this is a placeholder
69    }
70    
71    /// Render the status bar
72    pub fn render(&self, renderer: &mut Renderer, area: Rect) {
73        let mode_style = Style::default()
74            .fg(self.theme.background())
75            .bg(self.theme.primary());
76            
77        let file_style = Style::default()
78            .fg(self.theme.text())
79            .bg(self.theme.background_panel());
80            
81        let cursor_style = Style::default()
82            .fg(self.theme.text_muted())
83            .bg(self.theme.background_panel());
84        
85        // Build status line spans
86        let mut spans = vec![
87            Span::styled(format!(" {} ", self.mode), mode_style),
88            Span::raw(" "),
89        ];
90        
91        if let Some(ref path) = self.file_path {
92            spans.push(Span::styled(format!(" {} ", path), file_style));
93            spans.push(Span::raw(" "));
94        }
95        
96        // Add cursor position
97        spans.push(Span::styled(
98            format!(" {}:{} ", self.cursor_position.0, self.cursor_position.1),
99            cursor_style,
100        ));
101        
102        if let Some(ref selection) = self.selection_info {
103            spans.push(Span::raw(" "));
104            spans.push(Span::styled(format!(" {} ", selection), cursor_style));
105        }
106        
107        let status_line = Line::from(spans);
108        
109        let paragraph = Paragraph::new(vec![status_line])
110            .style(Style::default().bg(self.theme.background_panel()));
111            
112        renderer.render_widget(paragraph, area);
113    }
114}