use std::fmt::Debug;
use super::{super::Render, widget_base::WidgetBase, widget_type::WidgetType};
use crate::{
todo::ToDo,
ui::{HandleEvent, UIEvent},
};
use crossterm::event::KeyEvent;
use tui::{
prelude::Rect,
style::Style,
widgets::{Block, Borders},
Frame,
};
pub trait State: Debug {
fn handle_event_state(&mut self, event: UIEvent, todo: &mut ToDo) -> bool;
fn render(&self, f: &mut Frame, todo: &ToDo);
fn get_base(&self) -> &WidgetBase;
fn get_base_mut(&mut self) -> &mut WidgetBase;
fn get_block(&self) -> Block<'_> {
let base = self.get_base();
let mut block = Block::default()
.borders(Borders::ALL)
.title(base.title.clone())
.border_type(base.border_type.into());
if base.focus {
block = block.border_style(Style::default().fg(base.active_color));
}
block
}
fn focus_event(&mut self, _todo: &ToDo) -> bool {
true
}
fn unfocus_event(&mut self) {}
fn update_chunk_event(&mut self) {}
#[allow(unused_variables)]
fn search_event(&mut self, to_search: String) {}
fn clear_search(&mut self) {}
fn get_internal_event(&self, _: &KeyEvent) -> UIEvent {
UIEvent::None
}
#[allow(unused_variables)]
fn handle_click(&mut self, column: usize, row: usize, todo: &ToDo) {}
fn widget_type(&self) -> WidgetType;
}
impl<S: ?Sized + State> HandleEvent for S {
fn get_event(&self, key_event: &KeyEvent) -> UIEvent {
let event = self.get_internal_event(key_event);
if event == UIEvent::None {
self.get_base().event_handler.get_event(key_event)
} else {
event
}
}
fn handle_event(&mut self, event: UIEvent, todo: &mut ToDo) -> bool {
self.handle_event_state(event, todo)
}
fn click(&mut self, column: usize, row: usize, todo: &ToDo) {
self.handle_click(column, row, todo)
}
}
impl<S: ?Sized + State> Render for S {
fn render(&self, f: &mut Frame, todo: &ToDo) {
State::render(self, f, todo);
}
fn focus(&mut self, todo: &ToDo) -> bool {
let ret = self.focus_event(todo);
log::trace!(
"Widget {} try to focus with result: {}",
self.get_base().title,
ret
);
self.get_base_mut().focus = ret;
ret
}
fn unfocus(&mut self) {
self.unfocus_event();
log::trace!("Widget {} unfocus", self.get_base().title,);
self.get_base_mut().focus = false;
}
fn update_chunk(&mut self, chunk: Rect) {
self.get_base_mut().chunk = chunk;
self.update_chunk_event();
}
}