mirror of
https://github.com/ChrisTitusTech/linutil.git
synced 2024-11-22 05:12:27 +00:00
Made float.rs generic. It can show anything inside it now
This commit is contained in:
parent
c386fe8c37
commit
f0e67ba313
140
src/float.rs
140
src/float.rs
|
@ -1,59 +1,93 @@
|
||||||
use ratatui::layout::{Constraint, Direction, Layout, Rect};
|
use crossterm::event::{KeyCode, KeyEvent};
|
||||||
|
use ratatui::{
|
||||||
|
layout::{Constraint, Direction, Layout, Rect},
|
||||||
|
style::{Color, Style, Stylize},
|
||||||
|
widgets::Block,
|
||||||
|
Frame,
|
||||||
|
};
|
||||||
|
|
||||||
/// This function just makes a given area smaller by 20 % in each direction, creating a kind of
|
pub trait FloatContent {
|
||||||
/// "floating window". And you don't actually need all the constraints, and layouts to do that, its
|
fn draw(&mut self, frame: &mut Frame, area: Rect);
|
||||||
/// very easy to calculate it directly, but I chose to use the ratatui API
|
fn handle_key_event(&mut self, key: &KeyEvent) -> bool;
|
||||||
pub fn floating_window(size: Rect) -> Rect {
|
fn is_finished(&self) -> bool;
|
||||||
// If the terminal window is small enough, just take up all the space for the command
|
|
||||||
if size.width < 85 || size.height < 25 {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
let hor_float = Layout::default()
|
|
||||||
.constraints([
|
|
||||||
Constraint::Percentage(20),
|
|
||||||
Constraint::Percentage(60),
|
|
||||||
Constraint::Percentage(20),
|
|
||||||
])
|
|
||||||
.direction(Direction::Horizontal)
|
|
||||||
.split(size)[1];
|
|
||||||
Layout::default()
|
|
||||||
.constraints([
|
|
||||||
Constraint::Percentage(20),
|
|
||||||
Constraint::Percentage(60),
|
|
||||||
Constraint::Percentage(20),
|
|
||||||
])
|
|
||||||
.direction(Direction::Vertical)
|
|
||||||
.split(hor_float)[1]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Here is how would a purely math based function look like:
|
pub struct Float<T: FloatContent> {
|
||||||
/// But it might break on smaller numbers
|
content: Option<T>,
|
||||||
fn _unused_manual_floating_window(size: Rect) -> Rect {
|
width_percent: u16,
|
||||||
// If the terminal window is small enough, just take up all the space for the command
|
height_percent: u16,
|
||||||
if size.width < 85 || size.height < 25 {
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
let new_width = size.width * 60 / 100;
|
|
||||||
let new_height = size.height * 60 / 100;
|
|
||||||
let new_x = size.x + size.width * 20 / 100;
|
|
||||||
let new_y = size.y + size.height * 20 / 100;
|
|
||||||
Rect {
|
|
||||||
width: new_width,
|
|
||||||
height: new_height,
|
|
||||||
x: new_x,
|
|
||||||
y: new_y,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
impl<T: FloatContent> Float<T> {
|
||||||
fn test_floating() {
|
pub fn new(width_percent: u16, height_percent: u16) -> Self {
|
||||||
let rect = Rect {
|
Self {
|
||||||
x: 10,
|
content: None,
|
||||||
y: 2,
|
width_percent,
|
||||||
width: 100,
|
height_percent,
|
||||||
height: 200,
|
}
|
||||||
};
|
}
|
||||||
let res1 = floating_window(rect);
|
|
||||||
let res2 = floating_window(rect);
|
fn floating_window(&self, size: Rect) -> Rect {
|
||||||
assert_eq!(res1, res2);
|
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]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn draw(&mut self, frame: &mut Frame, parent_area: Rect) {
|
||||||
|
let popup_area = self.floating_window(parent_area);
|
||||||
|
|
||||||
|
if let Some(content) = &mut self.content {
|
||||||
|
let content_area = Rect {
|
||||||
|
x: popup_area.x,
|
||||||
|
y: popup_area.y,
|
||||||
|
width: popup_area.width,
|
||||||
|
height: popup_area.height,
|
||||||
|
};
|
||||||
|
|
||||||
|
content.draw(frame, content_area);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true if the key was processed by this Float.
|
||||||
|
pub fn handle_key_event(&mut self, key: &KeyEvent) -> bool {
|
||||||
|
if let Some(content) = &mut self.content {
|
||||||
|
match key.code {
|
||||||
|
KeyCode::Enter | KeyCode::Char('p') | KeyCode::Esc | KeyCode::Char('q') => {
|
||||||
|
if content.is_finished() {
|
||||||
|
self.content = None;
|
||||||
|
} else {
|
||||||
|
content.handle_key_event(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
content.handle_key_event(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_content(&self) -> &Option<T> {
|
||||||
|
&self.content
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_content(&mut self, content: Option<T>) {
|
||||||
|
self.content = content;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user