2026-01-19 09:23:12 -05:00
|
|
|
#![allow(dead_code, unused_variables)]
|
|
|
|
|
|
2026-01-20 17:19:13 -05:00
|
|
|
use anyhow::Result;
|
2026-01-25 09:07:41 -05:00
|
|
|
use log::trace;
|
2026-01-18 11:02:41 -05:00
|
|
|
use ratatui::crossterm::event::{Event, KeyEvent, MouseEvent};
|
2026-01-25 10:13:25 -05:00
|
|
|
use ratatui::style::Color;
|
2026-01-17 17:09:42 -05:00
|
|
|
|
|
|
|
|
pub enum Action {
|
2026-01-19 15:03:50 -05:00
|
|
|
/// Exit the application.
|
2026-01-17 17:09:42 -05:00
|
|
|
Quit,
|
2026-01-19 15:03:50 -05:00
|
|
|
|
|
|
|
|
/// The input was checked by the Component and had no effect.
|
|
|
|
|
Noop,
|
|
|
|
|
|
|
|
|
|
/// Pass input to another component or external handler.
|
|
|
|
|
/// Similar to Noop with the added context that externally handled input may have had an impact.
|
|
|
|
|
Pass,
|
|
|
|
|
|
|
|
|
|
/// Save the current file.
|
|
|
|
|
Save,
|
|
|
|
|
|
|
|
|
|
/// The input was handled by a Component and should not be passed to the next component.
|
|
|
|
|
Handled,
|
2026-01-24 19:41:38 -05:00
|
|
|
OpenTab,
|
2026-01-25 12:04:31 -05:00
|
|
|
ReloadFile,
|
|
|
|
|
ShowHideExplorer,
|
|
|
|
|
ShowHideLogger,
|
|
|
|
|
About,
|
|
|
|
|
CloseTab,
|
2026-01-17 17:09:42 -05:00
|
|
|
}
|
|
|
|
|
|
2026-01-19 09:23:12 -05:00
|
|
|
pub trait Component {
|
2026-01-20 17:19:13 -05:00
|
|
|
fn handle_event(&mut self, event: Event) -> Result<Action> {
|
2026-01-18 11:02:41 -05:00
|
|
|
match event {
|
|
|
|
|
Event::Key(key_event) => self.handle_key_events(key_event),
|
2026-01-20 17:19:13 -05:00
|
|
|
_ => Ok(Action::Noop),
|
2026-01-18 11:02:41 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-20 17:19:13 -05:00
|
|
|
fn handle_key_events(&mut self, key: KeyEvent) -> Result<Action> {
|
|
|
|
|
Ok(Action::Noop)
|
2026-01-17 17:09:42 -05:00
|
|
|
}
|
|
|
|
|
|
2026-01-20 17:19:13 -05:00
|
|
|
fn handle_mouse_events(&mut self, mouse: MouseEvent) -> Result<Action> {
|
|
|
|
|
Ok(Action::Noop)
|
2026-01-17 17:09:42 -05:00
|
|
|
}
|
|
|
|
|
|
2026-01-20 17:19:13 -05:00
|
|
|
fn update(&mut self, action: Action) -> Result<Action> {
|
|
|
|
|
Ok(Action::Noop)
|
2026-01-17 17:09:42 -05:00
|
|
|
}
|
2026-01-22 19:23:21 -05:00
|
|
|
|
|
|
|
|
/// Override this method for creating components that conditionally handle input.
|
|
|
|
|
fn is_active(&self) -> bool {
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 20:35:40 -05:00
|
|
|
#[derive(Debug, Clone, Default)]
|
2026-01-22 19:23:21 -05:00
|
|
|
pub struct ComponentState {
|
|
|
|
|
pub(crate) focus: Focus,
|
2026-01-22 20:35:40 -05:00
|
|
|
pub(crate) help_text: String,
|
2026-01-22 19:23:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ComponentState {
|
2026-01-25 09:07:41 -05:00
|
|
|
pub fn id() -> &'static str {
|
|
|
|
|
"ComponentState"
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 19:23:21 -05:00
|
|
|
fn new() -> Self {
|
2026-01-25 09:07:41 -05:00
|
|
|
trace!(target:Self::id(), "Building {}", Self::id());
|
2026-01-22 19:23:21 -05:00
|
|
|
Self {
|
|
|
|
|
focus: Focus::Active,
|
2026-01-22 20:35:40 -05:00
|
|
|
help_text: String::new(),
|
2026-01-22 19:23:21 -05:00
|
|
|
}
|
|
|
|
|
}
|
2026-01-22 20:35:40 -05:00
|
|
|
|
|
|
|
|
pub(crate) fn with_help_text(mut self, help_text: &str) -> Self {
|
|
|
|
|
self.help_text = help_text.into();
|
|
|
|
|
self
|
|
|
|
|
}
|
2026-01-22 19:23:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, Default, PartialEq)]
|
|
|
|
|
pub enum Focus {
|
|
|
|
|
Active,
|
|
|
|
|
#[default]
|
|
|
|
|
Inactive,
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-25 10:13:25 -05:00
|
|
|
impl Focus {
|
|
|
|
|
pub(crate) fn get_active_color(&self) -> Color {
|
|
|
|
|
match self {
|
|
|
|
|
Focus::Active => Color::LightYellow,
|
|
|
|
|
Focus::Inactive => Color::White,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-01-22 19:23:21 -05:00
|
|
|
pub trait FocusState {
|
|
|
|
|
fn with_focus(self, focus: Focus) -> Self;
|
|
|
|
|
fn set_focus(&mut self, focus: Focus);
|
|
|
|
|
fn toggle_focus(&mut self);
|
2026-01-25 10:13:25 -05:00
|
|
|
fn get_active_color(&self) -> Color;
|
2026-01-22 19:23:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl FocusState for ComponentState {
|
|
|
|
|
fn with_focus(self, focus: Focus) -> Self {
|
2026-01-22 20:35:40 -05:00
|
|
|
Self {
|
|
|
|
|
focus,
|
|
|
|
|
help_text: self.help_text,
|
|
|
|
|
}
|
2026-01-22 19:23:21 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn set_focus(&mut self, focus: Focus) {
|
|
|
|
|
self.focus = focus;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn toggle_focus(&mut self) {
|
|
|
|
|
match self.focus {
|
|
|
|
|
Focus::Active => self.set_focus(Focus::Inactive),
|
|
|
|
|
Focus::Inactive => self.set_focus(Focus::Active),
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-01-25 10:13:25 -05:00
|
|
|
|
|
|
|
|
fn get_active_color(&self) -> Color {
|
|
|
|
|
self.focus.get_active_color()
|
|
|
|
|
}
|
2026-01-17 17:09:42 -05:00
|
|
|
}
|