use crate::action::ActionList;
use crate::app::App;
use ratatui::{layout::Rect, Frame};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum SectionId {
Header,
WorkingDirectory,
MatchFiles,
Exclusions,
RenamingRule,
PreviewPane,
Validation,
ApplyRenaming,
Undo,
Footer,
}
impl SectionId {
pub fn all() -> Vec<SectionId> {
vec![
SectionId::Header,
SectionId::WorkingDirectory,
SectionId::MatchFiles,
SectionId::Exclusions,
SectionId::RenamingRule,
SectionId::PreviewPane,
SectionId::Validation,
SectionId::ApplyRenaming,
SectionId::Undo,
SectionId::Footer,
]
}
pub fn next(self) -> Option<SectionId> {
let all = Self::all();
let pos = all.iter().position(|&s| s == self)?;
if pos + 1 < all.len() {
Some(all[pos + 1])
} else {
None
}
}
pub fn previous(self) -> Option<SectionId> {
let all = Self::all();
let pos = all.iter().position(|&s| s == self)?;
if pos > 0 {
Some(all[pos - 1])
} else {
None
}
}
}
use crate::ui::section_layout::SectionHeights;
pub trait SectionTrait {
fn id(&self) -> SectionId;
fn title(&self) -> &str;
#[allow(dead_code)] fn hint(&self, app: &App) -> String;
#[allow(dead_code)] fn value(&self, app: &App) -> String;
fn actions(&self, app: &App) -> ActionList;
fn render(&self, f: &mut Frame, app: &App, area: Rect, is_focused: bool);
#[allow(dead_code)] fn handle_input(&self, app: &mut App, key: crossterm::event::KeyEvent) -> bool;
fn heights(&self) -> SectionHeights;
}
pub struct Section {
pub id: SectionId,
pub title: String,
#[allow(dead_code)] pub hint_getter: Box<dyn Fn(&App) -> String>,
#[allow(dead_code)] pub value_getter: Box<dyn Fn(&App) -> String>,
pub actions_getter: Box<dyn Fn(&App) -> ActionList>,
pub renderer: Box<dyn Fn(&mut Frame, &App, Rect, bool)>,
#[allow(dead_code)] pub input_handler: Box<dyn Fn(&mut App, crossterm::event::KeyEvent) -> bool>,
pub heights: SectionHeights,
}
impl Section {
pub fn new(
id: SectionId,
title: impl Into<String>,
hint_getter: impl Fn(&App) -> String + 'static,
value_getter: impl Fn(&App) -> String + 'static,
actions_getter: impl Fn(&App) -> ActionList + 'static,
renderer: impl Fn(&mut Frame, &App, Rect, bool) + 'static,
input_handler: impl Fn(&mut App, crossterm::event::KeyEvent) -> bool + 'static,
heights: SectionHeights,
) -> Self {
Self {
id,
title: title.into(),
hint_getter: Box::new(hint_getter),
value_getter: Box::new(value_getter),
actions_getter: Box::new(actions_getter),
renderer: Box::new(renderer),
input_handler: Box::new(input_handler),
heights,
}
}
}
impl SectionTrait for Section {
fn id(&self) -> SectionId {
self.id
}
fn title(&self) -> &str {
&self.title
}
fn hint(&self, app: &App) -> String {
(self.hint_getter)(app)
}
fn value(&self, app: &App) -> String {
(self.value_getter)(app)
}
fn actions(&self, app: &App) -> ActionList {
(self.actions_getter)(app)
}
fn render(&self, f: &mut Frame, app: &App, area: Rect, is_focused: bool) {
(self.renderer)(f, app, area, is_focused);
}
fn handle_input(&self, app: &mut App, key: crossterm::event::KeyEvent) -> bool {
(self.input_handler)(app, key)
}
fn heights(&self) -> SectionHeights {
self.heights
}
}