fresh/view/
event_debug.rs1use crate::app::event_debug::EventDebug;
6use crate::view::theme::Theme;
7use ratatui::{
8 layout::{Constraint, Layout, Rect},
9 style::{Modifier, Style},
10 text::{Line, Span},
11 widgets::{Block, Borders, Clear, Paragraph, Wrap},
12 Frame,
13};
14use rust_i18n::t;
15
16const DIALOG_WIDTH: u16 = 70;
18const DIALOG_HEIGHT: u16 = 18;
20
21pub fn render_event_debug(frame: &mut Frame, area: Rect, debug: &EventDebug, theme: &Theme) {
23 let dialog_height = DIALOG_HEIGHT.min(area.height.saturating_sub(4));
25 let dialog_width = DIALOG_WIDTH.min(area.width.saturating_sub(4));
26
27 let dialog_x = (area.width.saturating_sub(dialog_width)) / 2;
29 let dialog_y = (area.height.saturating_sub(dialog_height)) / 2;
30
31 let dialog_area = Rect {
32 x: dialog_x,
33 y: dialog_y,
34 width: dialog_width,
35 height: dialog_height,
36 };
37
38 frame.render_widget(Clear, dialog_area);
40
41 let block = Block::default()
43 .title(t!("event_debug.title").to_string())
44 .borders(Borders::ALL)
45 .border_style(Style::default().fg(theme.editor_fg))
46 .style(Style::default().bg(theme.editor_bg).fg(theme.editor_fg));
47
48 let inner_area = block.inner(dialog_area);
49 frame.render_widget(block, dialog_area);
50
51 let chunks = Layout::vertical([
53 Constraint::Length(3), Constraint::Min(8), Constraint::Length(4), ])
57 .split(inner_area);
58
59 let instructions = vec![
61 Line::from(vec![Span::styled(
62 t!("event_debug.instructions").to_string(),
63 Style::default().add_modifier(Modifier::BOLD),
64 )]),
65 Line::from(t!("event_debug.help_text").to_string()),
66 ];
67
68 let instructions_para = Paragraph::new(instructions)
69 .style(Style::default().fg(theme.editor_fg))
70 .wrap(Wrap { trim: true });
71 frame.render_widget(instructions_para, chunks[0]);
72
73 let mut history_lines: Vec<Line> = Vec::new();
75
76 if debug.history.is_empty() {
77 history_lines.push(Line::from(vec![Span::styled(
78 t!("event_debug.no_events").to_string(),
79 Style::default().fg(theme.line_number_fg),
80 )]));
81 } else {
82 history_lines.push(Line::from(vec![
83 Span::styled(
84 t!("event_debug.recent_events").to_string(),
85 Style::default()
86 .fg(theme.help_key_fg)
87 .add_modifier(Modifier::BOLD),
88 ),
89 Span::raw(format!(" ({})", debug.history.len())),
90 ]));
91 history_lines.push(Line::from(""));
92
93 for (i, recorded) in debug.history.iter().enumerate() {
94 let style = if i == 0 {
95 Style::default()
96 .fg(theme.diagnostic_info_fg)
97 .add_modifier(Modifier::BOLD)
98 } else {
99 Style::default().fg(theme.editor_fg)
100 };
101
102 let prefix = if i == 0 { "> " } else { " " };
103 history_lines.push(Line::from(vec![
104 Span::styled(prefix, style),
105 Span::styled(&recorded.description, style),
106 ]));
107 }
108 }
109
110 let history_para = Paragraph::new(history_lines).style(Style::default().fg(theme.editor_fg));
111 frame.render_widget(history_para, chunks[1]);
112
113 let mut control_lines = vec![Line::from(vec![
115 Span::styled("[q]", Style::default().fg(theme.help_key_fg)),
116 Span::raw(" "),
117 Span::raw(t!("event_debug.close").to_string()),
118 Span::raw(" "),
119 Span::styled("[Esc]", Style::default().fg(theme.help_key_fg)),
120 Span::raw(" "),
121 Span::raw(t!("event_debug.close").to_string()),
122 Span::raw(" "),
123 Span::styled("[c]", Style::default().fg(theme.help_key_fg)),
124 Span::raw(" "),
125 Span::raw(t!("event_debug.clear").to_string()),
126 ])];
127
128 if let Some(details) = debug.last_event_details() {
130 control_lines.push(Line::from(""));
131 control_lines.push(Line::from(vec![Span::styled(
132 details,
133 Style::default().fg(theme.line_number_fg),
134 )]));
135 }
136
137 let controls_para = Paragraph::new(control_lines)
138 .style(Style::default().fg(theme.editor_fg))
139 .wrap(Wrap { trim: true });
140 frame.render_widget(controls_para, chunks[2]);
141}