use std::any::Any;
use crossterm::event::MouseEvent;
use ratatui::buffer::Buffer;
use ratatui::layout::Rect;
use ratatui::style::Color;
use crate::{KeyChord, PanelEvent};
mod palette {
use ratatui::style::Color;
pub const BASE_00: Color = Color::Rgb(0x10, 0x14, 0x1b);
pub const BASE_01: Color = Color::Rgb(0x16, 0x1c, 0x25);
pub const BASE_02: Color = Color::Rgb(0x1a, 0x21, 0x2c);
pub const BASE_03: Color = Color::Rgb(0x2a, 0x32, 0x40);
pub const BASE_04: Color = Color::Rgb(0x5a, 0x6a, 0x80);
pub const BASE_05: Color = Color::Rgb(0x6b, 0x7b, 0x91);
pub const BASE_06: Color = Color::Rgb(0xa8, 0xb3, 0xc4);
pub const BASE_07: Color = Color::Rgb(0xc8, 0xd0, 0xdc);
pub const BASE_08: Color = Color::Rgb(0xe6, 0xec, 0xf5);
pub const ACCENT: Color = Color::Rgb(0x4f, 0x8c, 0xc9);
pub const ACCENT_BRIGHT: Color = Color::Rgb(0x7f, 0xb3, 0xe0);
pub const SELECT: Color = Color::Rgb(0x26, 0x36, 0x4d);
pub const SELECT_PRIMARY: Color = Color::Rgb(0x35, 0x50, 0x7a);
pub const RED: Color = Color::Rgb(0xe0, 0x6c, 0x75);
pub const AMBER: Color = Color::Rgb(0xe5, 0xc0, 0x7b);
pub const AMBER_DEEP: Color = Color::Rgb(0x3a, 0x35, 0x24);
pub const TEAL: Color = Color::Rgb(0x56, 0xb6, 0xc2);
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ThemeColors {
pub fg: Color,
pub bg: Color,
pub cursor_line_bg: Color,
pub gutter_fg: Color,
pub gutter_bg: Color,
pub line_number_fg: Color,
pub line_number_current_fg: Color,
pub selection_bg: Color,
pub selection_fg: Color,
pub selection_primary_bg: Color,
pub bracket_match_fg: Color,
pub bracket_match_bg: Color,
pub border: Color,
pub border_focused: Color,
pub status_bar_bg: Color,
pub status_bar_fg: Color,
pub status_bar_inactive_fg: Color,
pub status_bar_accent: Color,
pub tree_directory_fg: Color,
pub tree_file_fg: Color,
pub diagnostic_error: Color,
pub diagnostic_warning: Color,
pub diagnostic_info: Color,
pub diagnostic_hint: Color,
}
impl Default for ThemeColors {
fn default() -> Self {
use palette as p;
Self {
fg: p::BASE_07,
bg: p::BASE_00,
cursor_line_bg: p::BASE_01,
gutter_fg: p::BASE_04,
gutter_bg: p::BASE_00,
line_number_fg: p::BASE_04,
line_number_current_fg: p::BASE_07,
selection_bg: p::SELECT,
selection_fg: p::BASE_08,
selection_primary_bg: p::SELECT_PRIMARY,
bracket_match_fg: p::AMBER,
bracket_match_bg: p::AMBER_DEEP,
border: p::BASE_03,
border_focused: p::ACCENT,
status_bar_bg: p::BASE_02,
status_bar_fg: p::BASE_07,
status_bar_inactive_fg: p::BASE_05,
status_bar_accent: p::ACCENT,
tree_directory_fg: p::ACCENT_BRIGHT,
tree_file_fg: p::BASE_06,
diagnostic_error: p::RED,
diagnostic_warning: p::AMBER,
diagnostic_info: p::ACCENT,
diagnostic_hint: p::TEAL,
}
}
}
pub struct RenderContext<'a> {
pub theme: &'a ThemeColors,
pub is_focused: bool,
pub panel_index: usize,
pub terminal_width: u16,
pub terminal_height: u16,
}
pub trait Panel: Any {
fn name(&self) -> &'static str;
fn title(&self) -> String;
fn render(&mut self, area: Rect, buf: &mut Buffer, ctx: &RenderContext);
fn handle_key(&mut self, chord: KeyChord) -> Vec<PanelEvent>;
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn handle_mouse(&mut self, event: MouseEvent, panel_area: Rect) -> Vec<PanelEvent> {
let _ = (event, panel_area);
Vec::new()
}
fn handle_scroll(&mut self, delta: i32, panel_area: Rect) -> Vec<PanelEvent> {
let _ = (delta, panel_area);
Vec::new()
}
fn cursor_position(&self, panel_area: Rect) -> Option<(u16, u16)> {
let _ = panel_area;
None
}
fn apply_action(&mut self, action: crate::Action) -> Option<Vec<PanelEvent>> {
let _ = action;
None
}
fn tick(&mut self) -> Vec<PanelEvent> {
Vec::new()
}
fn captures_escape(&self) -> bool {
false
}
fn needs_close_confirmation(&self) -> Option<String> {
None
}
}