big ass refactor (rip client)

This commit is contained in:
🪞👃🪞 2024-07-03 14:51:48 +03:00
parent 94c1f83ef2
commit 8c3cf53c67
56 changed files with 2232 additions and 1891 deletions

View file

@ -0,0 +1,42 @@
pub enum Collected<'a> {
Box(Box<dyn Render + 'a>),
Ref(&'a (dyn Render + 'a)),
None
}
impl<'a> Render for Collected<'a> {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
match self {
Self::Box(item) => (*item).render(buf, area),
Self::Ref(item) => (*item).render(buf, area),
Self::None => Ok(area),
}
}
}
pub struct Collector<'a>(pub Vec<Collected<'a>>);
impl<'a, R: Render + 'a> FnOnce<(R)> for Collector<'a> {
type Output = ();
extern "rust-call" fn call_once (self, (device, ): (R,)) -> Self::Output {
self.add(widget.into_collected());
}
}
impl<'a> Collector<'a> {
pub fn collect (collect: impl Fn(&mut Collector<'a>)) -> Self {
let mut items = Self(vec![]);
collect(&mut items);
items
}
fn add (mut self, widget: Collected<'a>) -> Self {
self.0.push(widget);
self
}
}
pub trait Collection<'a, T, U> {
fn add (self, widget: impl Render + 'a) -> Self;
}

View file

@ -0,0 +1,73 @@
use crate::core::*;
pub struct Stack<'a>(pub &'a[Box<dyn Render + Sync>]);
impl<'a> Render for Stack<'a> {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
let mut area2 = area.clone();
for layer in self.0.iter() {
area2 = layer.render(buf, area2)?;
}
Ok(area)
}
}
pub struct Column(pub Vec<Box<dyn Device>>);
pub struct Row(pub Vec<Box<dyn Device>>);
impl Column {
pub fn new (items: Vec<Box<dyn Device>>) -> Self {
Self(items)
}
pub fn draw (buf: &mut Buffer, area: Rect, items: &[impl Render], gap: i16)
-> Usually<(Rect, Vec<Rect>)>
{
let mut w = 0u16;
let mut h = 0u16;
let mut rects = vec![];
for (_i, device) in items.iter().enumerate() {
let y = area.y + h;
let rect = Rect { x: area.x, y, width: area.width, height: area.height - h };
let result = device.render(buf, rect)?;
rects.push(result);
w = w.max(result.width);
h = ((h + result.height) as i16 + gap).max(0) as u16;
}
Ok((Rect { x: area.x, y: area.y, width: w, height: h }, rects))
}
}
impl Render for Column {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
Ok(Column::draw(buf, area, &self.0, 0)?.0)
}
}
impl Row {
pub fn new (items: Vec<Box<dyn Device>>) -> Self {
Self(items)
}
pub fn draw (buf: &mut Buffer, area: Rect, items: &[impl Render], gap: i16)
-> Usually<(Rect, Vec<Rect>)>
{
let mut w = 0u16;
let mut h = 0u16;
let mut rects = vec![];
for (_i, device) in items.iter().enumerate() {
let x = area.x + w;
let rect = Rect { x, y: area.y, width: area.width - w, height: area.height };
let result = device.render(buf, rect)?;
rects.push(result);
w = ((w + result.width) as i16 + gap).max(0) as u16;
h = h.max(result.height);
}
Ok((Rect { x: area.x, y: area.y, width: w, height: h }, rects))
}
}
impl Render for Row {
fn render (&self, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
Ok(Row::draw(buf, area, &self.0, 0)?.0)
}
}

0
src/view/layout/focus.rs Normal file
View file

View file

@ -0,0 +1,35 @@
use crate::core::*;
const LOZENGE: [[&'static str;3];3] = [
["", "", ""],
["", " ", ""],
["", "", ""],
];
pub fn lozenge_left (buf: &mut Buffer, x: u16, y1: u16, h: u16, style: Option<Style>) {
let y2 = y1 + h;
let y3 = y2.saturating_sub(1);
for y in y1..y2 {
if y == y1 {
LOZENGE[0][0]
} else if y == y3 {
LOZENGE[2][0]
} else {
LOZENGE[1][0]
}.blit(buf, x, y, style)
}
}
pub fn lozenge_right (buf: &mut Buffer, x: u16, y1: u16, h: u16, style: Option<Style>) {
let y2 = y1 + h;
let y3 = y2.saturating_sub(1);
for y in y1..y2 {
if y == y1 {
LOZENGE[0][2]
} else if y == y3 {
LOZENGE[2][2]
} else {
LOZENGE[1][2]
}.blit(buf, x, y, style)
}
}

53
src/view/layout/mod.rs Normal file
View file

@ -0,0 +1,53 @@
mod focus; pub use self::focus::*;
mod container; pub use self::container::*;
mod scroll; pub use self::scroll::*;
mod table; pub use self::table::*;
mod lozenge; pub use self::lozenge::*;
use crate::core::*;
pub trait Modal<T>: Device {
fn handle_with_state (&self, state: &mut T, event: &AppEvent) -> Usually<bool>;
}
pub trait MaxHeight: Device {
fn max_height (&self) -> u16 {
u16::MAX
}
}
impl<T: Device> MaxHeight for T {}
pub fn draw_box (buffer: &mut Buffer, area: Rect) -> Rect {
draw_box_styled(buffer, area, Some(Style::default().gray().dim()))
}
pub fn draw_box_styled (buffer: &mut Buffer, area: Rect, style: Option<Style>) -> Rect {
if area.width < 1 || area.height < 1 {
return area
}
format!("{}", "".repeat((area.width - 2).into()))
.blit(buffer, area.x, area.y, style);
for y in (area.y + 1)..(area.y + area.height - 1) {
"".blit(buffer, area.x, y, style);
"".blit(buffer, area.x + area.width - 1, y, style);
}
format!("{}", "".repeat((area.width - 2).into()))
.blit(buffer, area.x, area.y + area.height - 1, style);
area
}
pub fn draw_box_styled_dotted (buffer: &mut Buffer, area: Rect, style: Option<Style>) -> Rect {
if area.width < 1 || area.height < 1 {
return area
}
format!("{}", "".repeat((area.width - 2).into()))
.blit(buffer, area.x, area.y, style);
for y in (area.y + 1)..(area.y + area.height - 1) {
"".blit(buffer, area.x, y, style);
"".blit(buffer, area.x + area.width - 1, y, style);
}
format!("{}", "".repeat((area.width - 2).into()))
.blit(buffer, area.x, area.y + area.height - 1, style);
area
}

View file

@ -0,0 +1,5 @@
pub struct ScrollY;
pub struct ScrollX;
pub struct ScrollXY;

33
src/view/layout/table.rs Normal file
View file

@ -0,0 +1,33 @@
use crate::core::*;
pub struct Cell<T> {
text: String,
style: Option<Style>,
width: u16,
height: u16,
data: T
}
impl<T> Cell<T> {
pub fn new (text: &str, data: T) -> Self {
Self { text: text.to_string(), style: None, width: text.len() as u16, height: 1, data }
}
pub fn draw (&self, buf: &mut Buffer, x: u16, y: u16) {
self.text.blit(buf, x, y, self.style)
}
}
pub struct Table<T> {
columns: Vec<Vec<Cell<T>>>,
row: usize,
col: usize,
}
impl<T> Table<T> {
pub fn new (columns: Vec<Vec<Cell<T>>>) -> Self {
Self { columns, row: 0, col: 0 }
}
pub fn set (&mut self, col: usize, row: usize, cell: Cell<T>) {
self.columns[col][row] = cell;
}
}