1use crate::multiplexer::Multiplexer;
2use crate::pane::Pane;
3use crossterm::{cursor, style, terminal, QueueableCommand};
4use std::io::{self, Write};
5
6pub struct Renderer {
7 stdout: io::Stdout,
8}
9
10impl Renderer {
11 pub fn new() -> Self {
12 Self {
13 stdout: io::stdout(),
14 }
15 }
16
17 pub fn render_pane(&self, pane: &Pane, is_active: bool) -> io::Result<()> {
18 let mut stdout = io::stdout();
19 let buf = pane.buffer.lock().unwrap();
20 let (rows, cols) = buf.dimensions();
21
22 for row in 0..rows.min(pane.height as usize) {
23 stdout.queue(cursor::MoveTo(pane.x, pane.y + row as u16))?;
24 for col in 0..cols.min(pane.width as usize) {
25 let cell = buf.cell(row, col);
26 if cell.wide_continuation {
29 continue;
30 }
31 stdout.queue(style::SetForegroundColor(style::Color::Rgb {
32 r: cell.fg.r,
33 g: cell.fg.g,
34 b: cell.fg.b,
35 }))?;
36 stdout.queue(style::SetBackgroundColor(style::Color::Rgb {
37 r: cell.bg.r,
38 g: cell.bg.g,
39 b: cell.bg.b,
40 }))?;
41 if cell.bold {
42 stdout.queue(style::SetAttribute(style::Attribute::Bold))?;
43 }
44 stdout.queue(style::Print(cell.ch))?;
46 for &combining_ch in &cell.combining {
47 stdout.queue(style::Print(combining_ch))?;
48 }
49 if cell.bold {
50 stdout.queue(style::SetAttribute(style::Attribute::NoBold))?;
51 }
52 }
53 }
54
55 let (cursor_row, cursor_col) = buf.cursor();
56 if is_active {
57 stdout.queue(cursor::MoveTo(
58 pane.x + cursor_col as u16,
59 pane.y + cursor_row as u16,
60 ))?;
61 stdout.queue(cursor::Show)?;
62 }
63
64 stdout.queue(style::ResetColor)?;
65
66 Ok(())
67 }
68
69 pub fn render_status_bar(&self, mux: &Multiplexer) -> io::Result<()> {
70 let mut stdout = io::stdout();
71 let (cols, rows) = terminal::size()?;
72
73 stdout.queue(cursor::MoveTo(0, rows - 1))?;
74 stdout.queue(style::SetForegroundColor(style::Color::Rgb {
75 r: 200,
76 g: 200,
77 b: 200,
78 }))?;
79 stdout.queue(style::SetBackgroundColor(style::Color::Rgb {
80 r: 30,
81 g: 30,
82 b: 60,
83 }))?;
84
85 let prefix_indicator = if mux.is_prefix_mode() {
86 " [PREFIX] "
87 } else {
88 ""
89 };
90
91 let status = format!(
92 " KRONOS {} | {} | panes:{} | Ctrl+B=prefix{}",
93 env!("CARGO_PKG_VERSION"),
94 mux.active_pane_title(),
95 mux.pane_count(),
96 prefix_indicator,
97 );
98
99 let padded = format!("{:<width$}", status, width = cols as usize);
100 stdout.queue(style::Print(&padded[..padded.len().min(cols as usize)]))?;
101 stdout.queue(style::ResetColor)?;
102
103 Ok(())
104 }
105
106 pub fn flush(&mut self) -> io::Result<()> {
107 self.stdout.flush()
108 }
109}