toon_format/tui/components/
diff_viewer.rs1use ratatui::{
4 layout::{
5 Alignment,
6 Constraint,
7 Direction,
8 Layout,
9 Rect,
10 },
11 text::{
12 Line,
13 Span,
14 },
15 widgets::{
16 Block,
17 Borders,
18 Paragraph,
19 Wrap,
20 },
21 Frame,
22};
23
24use crate::tui::{
25 state::AppState,
26 theme::Theme,
27};
28
29pub struct DiffViewer;
30
31impl DiffViewer {
32 pub fn render(f: &mut Frame, area: Rect, app: &AppState, theme: &Theme) {
33 let block = Block::default()
34 .borders(Borders::ALL)
35 .border_style(theme.border_style(true))
36 .title(" Side-by-Side Comparison - Press Esc to close ")
37 .title_alignment(Alignment::Center);
38
39 let inner = block.inner(area);
40 f.render_widget(block, area);
41
42 let chunks = Layout::default()
43 .direction(Direction::Horizontal)
44 .constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
45 .split(inner);
46
47 let input_text = app.editor.get_input();
48 let input_title = match app.mode {
49 crate::tui::state::app_state::Mode::Encode => "JSON Input",
50 crate::tui::state::app_state::Mode::Decode => "TOON Input",
51 };
52
53 let input_lines: Vec<Line> = input_text
54 .lines()
55 .enumerate()
56 .map(|(idx, line)| {
57 Line::from(vec![
58 Span::styled(format!("{:4} ", idx + 1), theme.line_number_style()),
59 Span::styled(line, theme.normal_style()),
60 ])
61 })
62 .collect();
63
64 let input_para = Paragraph::new(input_lines)
65 .block(
66 Block::default()
67 .borders(Borders::ALL)
68 .border_style(theme.border_style(false))
69 .title(format!(" {input_title} ")),
70 )
71 .wrap(Wrap { trim: false });
72
73 f.render_widget(input_para, chunks[0]);
74
75 let output_text = app.editor.get_output();
76 let output_title = match app.mode {
77 crate::tui::state::app_state::Mode::Encode => "TOON Output",
78 crate::tui::state::app_state::Mode::Decode => "JSON Output",
79 };
80
81 let output_lines: Vec<Line> = output_text
82 .lines()
83 .enumerate()
84 .map(|(idx, line)| {
85 Line::from(vec![
86 Span::styled(format!("{:4} ", idx + 1), theme.line_number_style()),
87 Span::styled(line, theme.normal_style()),
88 ])
89 })
90 .collect();
91
92 let output_para = Paragraph::new(output_lines)
93 .block(
94 Block::default()
95 .borders(Borders::ALL)
96 .border_style(theme.border_style(false))
97 .title(format!(" {output_title} ")),
98 )
99 .wrap(Wrap { trim: false });
100
101 f.render_widget(output_para, chunks[1]);
102 }
103}