use crate::app::App;
use crate::theme::EverforestTheme as T;
use crate::types::AppMode;
use ratatui::layout::{Constraint, Direction, Layout, Rect};
use ratatui::style::{Modifier, Style};
use ratatui::text::Span;
use ratatui::widgets::Paragraph;
use ratatui::Frame;
pub fn render(frame: &mut Frame, app: &App, area: Rect) {
let sheet = app.stack.active();
let df = &sheet.dataframe;
let sel_count = df.selected_rows.len();
let chunks = Layout::default()
.direction(Direction::Horizontal)
.constraints([
Constraint::Length(10), Constraint::Min(20), Constraint::Length(8), Constraint::Length(26), ])
.split(area);
let mode_text = match app.mode {
AppMode::Normal => " NORMAL ",
AppMode::Searching => " SEARCH ",
AppMode::SelectByRegex => " SELECT ",
AppMode::ExpressionInput => " EXPR ",
AppMode::TypeSelect => " TYPE ",
AppMode::Editing => " EDIT ",
AppMode::Loading => " LOADING",
AppMode::Calculating => " CALC ",
AppMode::AggregatorSelect => " AGG ",
AppMode::GPrefix => " G-MODE ",
AppMode::Chart => " CHART ",
AppMode::Saving => " SAVING ",
AppMode::ZPrefix => " Z-MODE ",
AppMode::RenamingColumn => " RENAME ",
AppMode::InsertingColumn => " INSERT ",
AppMode::ConfirmQuit => " CONFIRM",
AppMode::YPrefix => " COPY ",
AppMode::CurrencySelect => " CURRENCY",
AppMode::PivotTableInput => " PIVOT ",
AppMode::PartitionSelect => " PART. ",
AppMode::Help => " HELP ",
AppMode::ChartAggSelect => " CHART ",
};
frame.render_widget(
Paragraph::new(mode_text).style(T::mode_indicator_style()),
chunks[0],
);
let modified = if df.modified { " [*]" } else { "" };
let stack_depth = app.stack.depth();
let depth_hint = if stack_depth > 1 {
format!("[sheets: {}] ", stack_depth)
} else {
String::new()
};
let base_status = format!(" {}{}{}", depth_hint, app.status_message, modified);
let final_status = if let Some((ref name, current, total)) = app.background_task {
let spinner_chars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
let spin = spinner_chars[(app.spinner_tick as usize) % spinner_chars.len()];
if total > 0 {
let pct = (current as f64 / total as f64 * 100.0) as usize;
format!(
"{} {} {}% ({}/{}) |{}",
spin, name, pct, current, total, base_status
)
} else {
format!("{} {}... |{}", spin, name, base_status)
}
} else if app.mode == AppMode::Calculating {
let spinner_chars = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
let spin = spinner_chars[(app.spinner_tick as usize) % spinner_chars.len()];
format!("{} {} |{}", spin, app.status_message, base_status)
} else {
base_status
};
frame.render_widget(
Paragraph::new(final_status).style(T::status_bar_style()),
chunks[1],
);
if sel_count > 0 {
let sel_text = format!(" {}● ", sel_count);
frame.render_widget(
Paragraph::new(Span::styled(
sel_text,
Style::default().fg(T::YELLOW).add_modifier(Modifier::BOLD),
))
.style(T::status_bar_style()),
chunks[2],
);
}
let row = sheet.table_state.selected().unwrap_or(0) + 1;
let total_rows = df.visible_row_count();
let col = sheet.cursor_col + 1;
let total_cols = df.col_count();
let pos_text = format!(" row {}/{} col {}/{} ", row, total_rows, col, total_cols);
frame.render_widget(
Paragraph::new(pos_text).style(T::status_bar_style()),
chunks[3],
);
}