use crate::core::geometry::{Point, Rect};
use crate::core::event::{Event, EventType, MB_LEFT_BUTTON};
use crate::core::draw::DrawBuffer;
use crate::core::state::StateFlags;
use crate::core::history::HistoryManager;
use crate::terminal::Terminal;
use super::view::{View, write_line_to_terminal};
use super::history_window::HistoryWindow;
pub struct History {
bounds: Rect,
history_id: u16,
state: StateFlags,
pub selected_item: Option<String>, palette_chain: Option<crate::core::palette_chain::PaletteChainNode>,
}
impl History {
pub fn new(pos: Point, history_id: u16) -> Self {
Self {
bounds: Rect::new(pos.x, pos.y, pos.x + 2, pos.y + 1),
history_id,
state: 0,
selected_item: None,
palette_chain: None,
}
}
pub fn has_items(&self) -> bool {
HistoryManager::has_history(self.history_id)
}
#[allow(dead_code)]
fn show_history(&mut self, terminal: &mut Terminal) {
if !self.has_items() {
return;
}
let window_pos = Point::new(
(self.bounds.a.x - 20).max(0),
self.bounds.a.y + 1,
);
let mut window = HistoryWindow::new(window_pos, self.history_id, 30);
if let Some(selected) = window.execute(terminal) {
self.selected_item = Some(selected);
}
}
}
impl View for History {
fn bounds(&self) -> Rect {
self.bounds
}
fn set_bounds(&mut self, bounds: Rect) {
self.bounds = bounds;
}
fn draw(&mut self, terminal: &mut Terminal) {
let mut buf = DrawBuffer::new(2);
let arrow = if self.has_items() { "▼" } else { " " };
use crate::core::palette::colors::{BUTTON_SELECTED, BUTTON_NORMAL};
let color = if self.is_focused() {
BUTTON_SELECTED
} else {
BUTTON_NORMAL
};
buf.move_str(0, arrow, color);
write_line_to_terminal(terminal, self.bounds.a.x, self.bounds.a.y, &buf);
}
fn handle_event(&mut self, event: &mut Event) {
match event.what {
EventType::MouseDown => {
if self.bounds.contains(event.mouse.pos) && event.mouse.buttons & MB_LEFT_BUTTON != 0 {
event.clear();
}
}
_ => {}
}
}
fn can_focus(&self) -> bool {
false }
fn state(&self) -> StateFlags {
self.state
}
fn set_state(&mut self, state: StateFlags) {
self.state = state;
}
fn set_palette_chain(&mut self, node: Option<crate::core::palette_chain::PaletteChainNode>) {
self.palette_chain = node;
}
fn get_palette_chain(&self) -> Option<&crate::core::palette_chain::PaletteChainNode> {
self.palette_chain.as_ref()
}
fn get_palette(&self) -> Option<crate::core::palette::Palette> {
use crate::core::palette::{palettes, Palette};
Some(Palette::from_slice(palettes::CP_HISTORY))
}
}
pub struct HistoryBuilder {
pos: Option<Point>,
history_id: Option<u16>,
}
impl HistoryBuilder {
pub fn new() -> Self {
Self { pos: None, history_id: None }
}
#[must_use]
pub fn pos(mut self, pos: Point) -> Self {
self.pos = Some(pos);
self
}
#[must_use]
pub fn history_id(mut self, history_id: u16) -> Self {
self.history_id = Some(history_id);
self
}
pub fn build(self) -> History {
let pos = self.pos.expect("History pos must be set");
let history_id = self.history_id.expect("History history_id must be set");
History::new(pos, history_id)
}
pub fn build_boxed(self) -> Box<History> {
Box::new(self.build())
}
}
impl Default for HistoryBuilder {
fn default() -> Self {
Self::new()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_history_button_creation() {
HistoryManager::clear_all();
let button = History::new(Point::new(20, 5), 1);
assert!(!button.has_items());
assert_eq!(button.bounds.width(), 2);
}
#[test]
fn test_history_button_with_items() {
HistoryManager::clear_all();
HistoryManager::add(2, "test".to_string());
let button = History::new(Point::new(20, 5), 2);
assert!(button.has_items());
}
}