use std::collections::{HashMap, HashSet};
use crossterm::{cursor, queue, terminal};
use crate::layout::Layout;
use crate::pane::Pane;
use crate::render::{self, BorderCache};
use crate::settings::Settings;
use super::state::InputMode;
#[allow(clippy::too_many_arguments)]
pub(crate) fn render_frame_to_buf(
buf: &mut Vec<u8>,
panes: &HashMap<usize, Pane>,
layout: &Layout,
active: usize,
settings: &Settings,
tw: u16,
th: u16,
dragging: bool,
border_cache: &BorderCache,
dirty_panes: &HashSet<usize>,
full_redraw: bool,
mode: &InputMode,
broadcast: bool,
selection: render::PaneSelection,
selection_chars: usize,
zoomed_pane: Option<usize>,
default_shell: &str,
tab_names: &[(usize, String, bool)],
) -> anyhow::Result<()> {
let mode_label = match mode {
InputMode::Prefix { .. } => "PREFIX",
InputMode::CopyMode(ref cm) => cm.mode_label(),
InputMode::QuitConfirm => "KILL SESSION? y/n",
InputMode::CloseConfirm => "CLOSE PANE? y/n",
InputMode::CloseTabConfirm => "CLOSE TAB? y/n",
InputMode::ResizeMode => "RESIZE",
InputMode::PaneSelect => "SELECT",
InputMode::HelpOverlay => "",
InputMode::RenameTab { .. } => "RENAME",
InputMode::CommandPalette { .. } => ":",
InputMode::Normal if broadcast => "BROADCAST",
InputMode::Normal => "",
};
if let Some(zpid) = zoomed_pane {
queue!(buf, terminal::BeginSynchronizedUpdate)?;
let pane_order = border_cache.pane_order();
let pane_idx = pane_order.iter().position(|&id| id == zpid).unwrap_or(0);
let label = panes
.get(&zpid)
.map(|p| p.launch_label(default_shell))
.unwrap_or_default();
if let Some(pane) = panes.get(&zpid) {
render::render_zoomed_pane(
buf,
pane,
pane_idx,
&label,
settings.border_style,
tw,
th,
settings.show_status_bar,
&settings.theme,
)?;
}
if settings.show_status_bar {
let zoom_label = if mode_label.is_empty() {
"ZOOM"
} else {
mode_label
};
let pane_name = panes.get(&zpid).and_then(|p| p.name()).unwrap_or("");
render::draw_status_bar_full(
buf,
tw,
th,
pane_idx,
pane_order.len(),
zoom_label,
pane_name,
0,
&settings.theme,
)?;
}
queue!(buf, terminal::EndSynchronizedUpdate)?;
} else {
queue!(buf, terminal::BeginSynchronizedUpdate)?;
render::render_panes(
buf,
panes,
layout,
active,
settings.border_style,
settings.show_status_bar,
tw,
th,
dragging,
border_cache,
dirty_panes,
full_redraw,
selection,
broadcast,
&settings.theme,
)?;
let is_text_input = matches!(
mode,
InputMode::RenameTab { .. } | InputMode::CommandPalette { .. }
);
if !is_text_input
&& settings.show_status_bar
&& (!mode_label.is_empty() || selection_chars > 0)
{
let pane_order = border_cache.pane_order();
let active_idx = pane_order.iter().position(|&id| id == active).unwrap_or(0);
let pane_name = panes.get(&active).and_then(|p| p.name()).unwrap_or("");
render::draw_status_bar_full(
buf,
tw,
th,
active_idx,
pane_order.len(),
mode_label,
pane_name,
selection_chars,
&settings.theme,
)?;
}
if settings.visible {
settings.render_overlay(buf, tw, th, broadcast)?;
queue!(buf, cursor::Hide)?;
}
queue!(buf, terminal::EndSynchronizedUpdate)?;
}
if tab_names.len() > 1 && settings.show_tab_bar {
render::draw_tab_bar(
buf,
tw,
th,
tab_names,
settings.show_status_bar,
&settings.theme,
)?;
}
if matches!(mode, InputMode::HelpOverlay) {
render::draw_help_overlay(buf, tw, th, &settings.theme)?;
}
if matches!(mode, InputMode::PaneSelect) {
let inner = crate::app::render_ctl::make_inner(tw, th, settings.show_status_bar);
render::draw_pane_numbers(buf, layout, &inner, &settings.theme)?;
}
match mode {
InputMode::RenameTab { buffer } => {
render::draw_text_input(buf, tw, th, "Rename tab: ", buffer, &settings.theme)?;
}
InputMode::CommandPalette { buffer } => {
render::draw_text_input(buf, tw, th, ":", buffer, &settings.theme)?;
}
_ => {}
}
queue!(buf, cursor::Hide)?;
Ok(())
}