use super::content::{HelpContent, HelpSection, Shortcut};
use crate::theme::ThemeManager;
use tuirealm::ratatui::{
layout::{Alignment, Constraint, Layout, Rect},
style::{Modifier, Style},
text::{Line, Span, Text},
widgets::{Block, Paragraph as RatatuiParagraph},
};
pub struct HelpRenderer {
key_width: usize,
}
impl HelpRenderer {
pub fn new() -> Self {
Self { key_width: 20 }
}
pub fn render_help_content<'a>(&self, content: &'a HelpContent) -> (Text<'a>, Text<'a>) {
let sections = &content.sections;
let mid_point = sections.len().div_ceil(2);
let left_sections = §ions[0..mid_point];
let right_sections = §ions[mid_point..];
let left_content = self.render_sections(left_sections);
let right_content = self.render_sections(right_sections);
(left_content, right_content)
}
pub fn render_header<'a>(&self, content: &'a HelpContent) -> Text<'a> {
Text::from(vec![
Line::from(vec![Span::styled(
&content.header_message,
Style::default()
.fg(ThemeManager::shortcut_description())
.add_modifier(Modifier::BOLD),
)]),
Line::from(vec![Span::styled(
&content.warning_message,
Style::default().fg(ThemeManager::status_warning()),
)]),
])
}
fn render_sections<'a>(&self, sections: &'a [HelpSection]) -> Text<'a> {
let mut lines = Vec::new();
for section in sections {
if section.title == "Note" {
lines.push(Line::from(vec![Span::styled(
"Note: Operations work on selected messages in bulk mode,",
Style::default().fg(ThemeManager::status_info()),
)]));
lines.push(Line::from(vec![Span::styled(
" or on current message when no selections exist.",
Style::default().fg(ThemeManager::status_info()),
)]));
lines.push(Line::from(""));
continue;
}
if !section.title.is_empty() {
lines.push(Line::from(vec![Span::styled(
format!("{} {}", section.icon, section.title),
Style::default()
.fg(ThemeManager::help_section_title())
.add_modifier(Modifier::BOLD),
)]));
lines.push(Line::from(""));
}
for shortcut in §ion.shortcuts {
lines.push(self.render_shortcut(shortcut));
}
if !section.title.is_empty() {
lines.push(Line::from(""));
}
}
Text::from(lines)
}
fn render_shortcut<'a>(&self, shortcut: &'a Shortcut) -> Line<'a> {
let key_text = if shortcut.keys.len() == 1 {
shortcut.keys[0].clone()
} else {
shortcut.keys.join(" ")
};
if shortcut.description.is_empty() {
return Line::from(vec![Span::styled(
key_text,
Style::default().fg(ThemeManager::status_info()),
)]);
}
Line::from(vec![
Span::styled(
format!(" {:width$}", key_text, width = self.key_width),
Style::default()
.fg(ThemeManager::shortcut_key())
.add_modifier(Modifier::BOLD),
),
Span::styled(
&shortcut.description,
Style::default().fg(ThemeManager::shortcut_description()),
),
])
}
pub fn create_paragraph<'a>(
&self,
text: Text<'a>,
alignment: Alignment,
) -> RatatuiParagraph<'a> {
RatatuiParagraph::new(text)
.alignment(alignment)
.block(Block::default())
}
pub fn layout_help_screen(&self, area: Rect) -> (Rect, Rect, Rect) {
let chunks = Layout::default()
.constraints([Constraint::Length(3), Constraint::Min(0)])
.margin(1)
.split(area);
let columns = Layout::default()
.direction(tuirealm::ratatui::layout::Direction::Horizontal)
.constraints([Constraint::Percentage(50), Constraint::Percentage(50)])
.split(chunks[1]);
(chunks[0], columns[0], columns[1])
}
}
impl Default for HelpRenderer {
fn default() -> Self {
Self::new()
}
}