2024-08-06 17:21:47 +01:00
|
|
|
use crossterm::event::{KeyCode, KeyEvent};
|
|
|
|
use ratatui::{
|
|
|
|
layout::{Constraint, Direction, Layout, Rect},
|
|
|
|
Frame,
|
|
|
|
};
|
|
|
|
|
|
|
|
pub trait FloatContent {
|
|
|
|
fn draw(&mut self, frame: &mut Frame, area: Rect);
|
|
|
|
fn handle_key_event(&mut self, key: &KeyEvent) -> bool;
|
|
|
|
fn is_finished(&self) -> bool;
|
|
|
|
}
|
|
|
|
|
2024-08-09 10:22:19 +01:00
|
|
|
pub struct Float {
|
|
|
|
content: Box<dyn FloatContent>,
|
2024-08-06 17:21:47 +01:00
|
|
|
width_percent: u16,
|
|
|
|
height_percent: u16,
|
2024-06-06 23:56:45 +01:00
|
|
|
}
|
|
|
|
|
2024-08-09 10:22:19 +01:00
|
|
|
impl Float {
|
|
|
|
pub fn new(content: Box<dyn FloatContent>, width_percent: u16, height_percent: u16) -> Self {
|
2024-08-06 17:21:47 +01:00
|
|
|
Self {
|
2024-08-09 10:22:19 +01:00
|
|
|
content,
|
2024-08-06 17:21:47 +01:00
|
|
|
width_percent,
|
|
|
|
height_percent,
|
|
|
|
}
|
2024-06-06 23:56:45 +01:00
|
|
|
}
|
2024-08-06 17:21:47 +01:00
|
|
|
|
|
|
|
fn floating_window(&self, size: Rect) -> Rect {
|
|
|
|
let hor_float = Layout::default()
|
|
|
|
.constraints([
|
|
|
|
Constraint::Percentage((100 - self.width_percent) / 2),
|
|
|
|
Constraint::Percentage(self.width_percent),
|
|
|
|
Constraint::Percentage((100 - self.width_percent) / 2),
|
|
|
|
])
|
|
|
|
.direction(Direction::Horizontal)
|
|
|
|
.split(size)[1];
|
|
|
|
|
|
|
|
Layout::default()
|
|
|
|
.constraints([
|
|
|
|
Constraint::Percentage((100 - self.height_percent) / 2),
|
|
|
|
Constraint::Percentage(self.height_percent),
|
|
|
|
Constraint::Percentage((100 - self.height_percent) / 2),
|
|
|
|
])
|
|
|
|
.direction(Direction::Vertical)
|
|
|
|
.split(hor_float)[1]
|
2024-06-06 23:56:45 +01:00
|
|
|
}
|
|
|
|
|
2024-08-06 17:21:47 +01:00
|
|
|
pub fn draw(&mut self, frame: &mut Frame, parent_area: Rect) {
|
|
|
|
let popup_area = self.floating_window(parent_area);
|
|
|
|
|
2024-08-09 10:22:19 +01:00
|
|
|
let content_area = Rect {
|
|
|
|
x: popup_area.x,
|
|
|
|
y: popup_area.y,
|
|
|
|
width: popup_area.width,
|
|
|
|
height: popup_area.height,
|
|
|
|
};
|
2024-08-06 17:21:47 +01:00
|
|
|
|
2024-08-09 10:22:19 +01:00
|
|
|
self.content.draw(frame, content_area);
|
2024-08-06 17:21:47 +01:00
|
|
|
}
|
|
|
|
|
2024-08-09 10:22:19 +01:00
|
|
|
// Returns true if the floating window is finished.
|
2024-08-06 17:21:47 +01:00
|
|
|
pub fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
|
2024-08-09 10:22:19 +01:00
|
|
|
match key.code {
|
|
|
|
KeyCode::Enter | KeyCode::Char('p') | KeyCode::Esc | KeyCode::Char('q')
|
|
|
|
if self.content.is_finished() =>
|
|
|
|
{
|
|
|
|
true
|
2024-08-06 17:21:47 +01:00
|
|
|
}
|
2024-08-09 10:22:19 +01:00
|
|
|
_ => self.content.handle_key_event(key),
|
2024-08-06 17:21:47 +01:00
|
|
|
}
|
|
|
|
}
|
2024-06-06 23:56:45 +01:00
|
|
|
}
|