extract tui_border.rs

This commit is contained in:
🪞👃🪞 2024-12-16 19:12:50 +01:00
parent e57415aac9
commit 6cc81acd70
3 changed files with 212 additions and 205 deletions

View file

@ -4,6 +4,7 @@ mod tui_input; pub(crate) use tui_input::*;
mod tui_style; pub(crate) use tui_style::*;
mod tui_theme; pub(crate) use tui_theme::*;
mod tui_output; pub(crate) use tui_output::*;
mod tui_border; pub(crate) use tui_border::*;
////////////////////////////////////////////////////////

View file

@ -0,0 +1,211 @@
use crate::*;
pub struct Bordered<S: BorderStyle, W: Render<Tui>>(pub S, pub W);
render!(|self: Bordered<S: BorderStyle, W: Render<Tui>>|{
Tui::fill_xy(lay!([Border(self.0), Tui::inset_xy(1, 1, widget(&self.1))]))
});
pub struct Border<S: BorderStyle>(pub S);
impl<S: BorderStyle> Render<Tui> for Border<S> {
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
Ok(Some([0, 0]))
}
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
let area = to.area();
if area.w() > 0 && area.y() > 0 {
to.blit(&self.0.nw(), area.x(), area.y(), self.0.style());
to.blit(&self.0.ne(), area.x() + area.w() - 1, area.y(), self.0.style());
to.blit(&self.0.sw(), area.x(), area.y() + area.h() - 1, self.0.style());
to.blit(&self.0.se(), area.x() + area.w() - 1, area.y() + area.h() - 1, self.0.style());
for x in area.x()+1..area.x()+area.w()-1 {
to.blit(&self.0.n(), x, area.y(), self.0.style());
to.blit(&self.0.s(), x, area.y() + area.h() - 1, self.0.style());
}
for y in area.y()+1..area.y()+area.h()-1 {
to.blit(&self.0.w(), area.x(), y, self.0.style());
to.blit(&self.0.e(), area.x() + area.w() - 1, y, self.0.style());
}
}
Ok(())
}
}
pub trait BorderStyle: Send + Sync + Copy {
fn wrap <W: Render<Tui>> (self, w: W) -> Bordered<Self, W> {
Bordered(self, w)
}
const NW: &'static str = "";
const N: &'static str = "";
const NE: &'static str = "";
const E: &'static str = "";
const SE: &'static str = "";
const S: &'static str = "";
const SW: &'static str = "";
const W: &'static str = "";
fn n (&self) -> &str { Self::N }
fn s (&self) -> &str { Self::S }
fn e (&self) -> &str { Self::E }
fn w (&self) -> &str { Self::W }
fn nw (&self) -> &str { Self::NW }
fn ne (&self) -> &str { Self::NE }
fn sw (&self) -> &str { Self::SW }
fn se (&self) -> &str { Self::SE }
#[inline] fn draw <'a> (
&self, to: &mut TuiOutput
) -> Usually<()> {
self.draw_horizontal(to, None)?;
self.draw_vertical(to, None)?;
self.draw_corners(to, None)?;
Ok(())
}
#[inline] fn draw_horizontal (
&self, to: &mut TuiOutput, style: Option<Style>
) -> Usually<[u16;4]> {
let area = to.area();
let style = style.or_else(||self.style_horizontal());
let [x, x2, y, y2] = area.lrtb();
for x in x..x2.saturating_sub(1) {
self.draw_north(to, x, y, style);
self.draw_south(to, x, y2.saturating_sub(1), style);
}
Ok(area)
}
#[inline] fn draw_north (
&self, to: &mut TuiOutput, x: u16, y: u16, style: Option<Style>
) -> () {
to.blit(&Self::N, x, y, style)
}
#[inline] fn draw_south (
&self, to: &mut TuiOutput, x: u16, y: u16, style: Option<Style>
) -> () {
to.blit(&Self::S, x, y, style)
}
#[inline] fn draw_vertical (
&self, to: &mut TuiOutput, style: Option<Style>
) -> Usually<[u16;4]> {
let area = to.area();
let style = style.or_else(||self.style_vertical());
let [x, x2, y, y2] = area.lrtb();
for y in y..y2.saturating_sub(1) {
to.blit(&Self::W, x, y, style);
to.blit(&Self::E, x2.saturating_sub(1), y, style);
}
Ok(area)
}
#[inline] fn draw_corners (
&self, to: &mut TuiOutput, style: Option<Style>
) -> Usually<[u16;4]> {
let area = to.area();
let style = style.or_else(||self.style_corners());
let [x, y, width, height] = area.xywh();
if width > 0 && height > 0 {
to.blit(&Self::NW, x, y, style);
to.blit(&Self::NE, x + width - 1, y, style);
to.blit(&Self::SW, x, y + height - 1, style);
to.blit(&Self::SE, x + width - 1, y + height - 1, style);
}
Ok(area)
}
#[inline] fn style (&self) -> Option<Style> { None }
#[inline] fn style_horizontal (&self) -> Option<Style> { self.style() }
#[inline] fn style_vertical (&self) -> Option<Style> { self.style() }
#[inline] fn style_corners (&self) -> Option<Style> { self.style() }
}
macro_rules! border {
($($T:ident {
$nw:literal $n:literal $ne:literal $w:literal $e:literal $sw:literal $s:literal $se:literal
$($x:tt)*
}),+) => {$(
impl BorderStyle for $T {
const NW: &'static str = $nw;
const N: &'static str = $n;
const NE: &'static str = $ne;
const W: &'static str = $w;
const E: &'static str = $e;
const SW: &'static str = $sw;
const S: &'static str = $s;
const SE: &'static str = $se;
$($x)*
}
#[derive(Copy, Clone)]
pub struct $T(pub Style);
impl Render<Tui> for $T {
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> { Ok(Some([0,0])) }
fn render (&self, to: &mut TuiOutput) -> Usually<()> { self.draw(to) }
}
)+}
}
border! {
Square {
"" "" ""
"" ""
"" "" "" fn style (&self) -> Option<Style> { Some(self.0) }
},
SquareBold {
"" "" ""
"" ""
"" "" "" fn style (&self) -> Option<Style> { Some(self.0) }
},
Tab {
"" "" ""
"" ""
"" " " "" fn style (&self) -> Option<Style> { Some(self.0) }
},
Lozenge {
"" "" ""
"" ""
"" "" "" fn style (&self) -> Option<Style> { Some(self.0) }
},
Brace {
"" "" ""
"" ""
"" "" "" fn style (&self) -> Option<Style> { Some(self.0) }
},
LozengeDotted {
"" "" ""
"" ""
"" "" "" fn style (&self) -> Option<Style> { Some(self.0) }
},
Quarter {
"" "" "🮇"
"" "🮇"
"" "" "🮇" fn style (&self) -> Option<Style> { Some(self.0) }
},
QuarterV {
"" "" "🮇"
"" "🮇"
"" "" "🮇" fn style (&self) -> Option<Style> { Some(self.0) }
},
Chamfer {
"🭂" "" "🭍"
"" "🮇"
"🭓" "" "🭞" fn style (&self) -> Option<Style> { Some(self.0) }
},
Corners {
"🬆" "" "🬊" // 🬴 🬸
"" ""
"🬱" "" "🬵" fn style (&self) -> Option<Style> { Some(self.0) }
},
CornersTall {
"🭽" "" "🭾"
"" ""
"🭼" "" "🭿" fn style (&self) -> Option<Style> { Some(self.0) }
},
Brackets {
"" "" ""
"" ""
"" "" "" fn style (&self) -> Option<Style> { Some(self.0) }
}
}
pub const CORNERS: Brackets = Brackets(Style {
fg: Some(Color::Rgb(96, 255, 32)),
bg: None,
underline_color: None,
add_modifier: Modifier::empty(),
sub_modifier: Modifier::DIM
});

View file

@ -54,38 +54,6 @@ impl<W: Render<Tui>> Render<Tui> for Background<W> {
}
}
pub struct Bordered<S: BorderStyle, W: Render<Tui>>(pub S, pub W);
render!(|self: Bordered<S: BorderStyle, W: Render<Tui>>|{
Tui::fill_xy(lay!([Border(self.0), Tui::inset_xy(1, 1, widget(&self.1))]))
});
pub struct Border<S: BorderStyle>(pub S);
impl<S: BorderStyle> Render<Tui> for Border<S> {
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> {
Ok(Some([0, 0]))
}
fn render (&self, to: &mut TuiOutput) -> Usually<()> {
let area = to.area();
if area.w() > 0 && area.y() > 0 {
to.blit(&self.0.nw(), area.x(), area.y(), self.0.style());
to.blit(&self.0.ne(), area.x() + area.w() - 1, area.y(), self.0.style());
to.blit(&self.0.sw(), area.x(), area.y() + area.h() - 1, self.0.style());
to.blit(&self.0.se(), area.x() + area.w() - 1, area.y() + area.h() - 1, self.0.style());
for x in area.x()+1..area.x()+area.w()-1 {
to.blit(&self.0.n(), x, area.y(), self.0.style());
to.blit(&self.0.s(), x, area.y() + area.h() - 1, self.0.style());
}
for y in area.y()+1..area.y()+area.h()-1 {
to.blit(&self.0.w(), area.x(), y, self.0.style());
to.blit(&self.0.e(), area.x() + area.w() - 1, y, self.0.style());
}
}
Ok(())
}
}
pub struct Styled<T: Render<Tui>>(pub Option<Style>, pub T);
impl Render<Tui> for Styled<&str> {
@ -100,179 +68,6 @@ impl Render<Tui> for Styled<&str> {
}
}
pub trait BorderStyle: Send + Sync + Copy {
fn wrap <W: Render<Tui>> (self, w: W) -> Bordered<Self, W> {
Bordered(self, w)
}
const NW: &'static str = "";
const N: &'static str = "";
const NE: &'static str = "";
const E: &'static str = "";
const SE: &'static str = "";
const S: &'static str = "";
const SW: &'static str = "";
const W: &'static str = "";
fn n (&self) -> &str { Self::N }
fn s (&self) -> &str { Self::S }
fn e (&self) -> &str { Self::E }
fn w (&self) -> &str { Self::W }
fn nw (&self) -> &str { Self::NW }
fn ne (&self) -> &str { Self::NE }
fn sw (&self) -> &str { Self::SW }
fn se (&self) -> &str { Self::SE }
#[inline] fn draw <'a> (
&self, to: &mut TuiOutput
) -> Usually<()> {
self.draw_horizontal(to, None)?;
self.draw_vertical(to, None)?;
self.draw_corners(to, None)?;
Ok(())
}
#[inline] fn draw_horizontal (
&self, to: &mut TuiOutput, style: Option<Style>
) -> Usually<[u16;4]> {
let area = to.area();
let style = style.or_else(||self.style_horizontal());
let [x, x2, y, y2] = area.lrtb();
for x in x..x2.saturating_sub(1) {
self.draw_north(to, x, y, style);
self.draw_south(to, x, y2.saturating_sub(1), style);
}
Ok(area)
}
#[inline] fn draw_north (
&self, to: &mut TuiOutput, x: u16, y: u16, style: Option<Style>
) -> () {
to.blit(&Self::N, x, y, style)
}
#[inline] fn draw_south (
&self, to: &mut TuiOutput, x: u16, y: u16, style: Option<Style>
) -> () {
to.blit(&Self::S, x, y, style)
}
#[inline] fn draw_vertical (
&self, to: &mut TuiOutput, style: Option<Style>
) -> Usually<[u16;4]> {
let area = to.area();
let style = style.or_else(||self.style_vertical());
let [x, x2, y, y2] = area.lrtb();
for y in y..y2.saturating_sub(1) {
to.blit(&Self::W, x, y, style);
to.blit(&Self::E, x2.saturating_sub(1), y, style);
}
Ok(area)
}
#[inline] fn draw_corners (
&self, to: &mut TuiOutput, style: Option<Style>
) -> Usually<[u16;4]> {
let area = to.area();
let style = style.or_else(||self.style_corners());
let [x, y, width, height] = area.xywh();
if width > 0 && height > 0 {
to.blit(&Self::NW, x, y, style);
to.blit(&Self::NE, x + width - 1, y, style);
to.blit(&Self::SW, x, y + height - 1, style);
to.blit(&Self::SE, x + width - 1, y + height - 1, style);
}
Ok(area)
}
#[inline] fn style (&self) -> Option<Style> { None }
#[inline] fn style_horizontal (&self) -> Option<Style> { self.style() }
#[inline] fn style_vertical (&self) -> Option<Style> { self.style() }
#[inline] fn style_corners (&self) -> Option<Style> { self.style() }
}
macro_rules! border {
($($T:ident {
$nw:literal $n:literal $ne:literal $w:literal $e:literal $sw:literal $s:literal $se:literal
$($x:tt)*
}),+) => {$(
impl BorderStyle for $T {
const NW: &'static str = $nw;
const N: &'static str = $n;
const NE: &'static str = $ne;
const W: &'static str = $w;
const E: &'static str = $e;
const SW: &'static str = $sw;
const S: &'static str = $s;
const SE: &'static str = $se;
$($x)*
}
#[derive(Copy, Clone)]
pub struct $T(pub Style);
impl Render<Tui> for $T {
fn min_size (&self, _: [u16;2]) -> Perhaps<[u16;2]> { Ok(Some([0,0])) }
fn render (&self, to: &mut TuiOutput) -> Usually<()> { self.draw(to) }
}
)+}
}
border! {
Square {
"" "" ""
"" ""
"" "" "" fn style (&self) -> Option<Style> { Some(self.0) }
},
SquareBold {
"" "" ""
"" ""
"" "" "" fn style (&self) -> Option<Style> { Some(self.0) }
},
Tab {
"" "" ""
"" ""
"" " " "" fn style (&self) -> Option<Style> { Some(self.0) }
},
Lozenge {
"" "" ""
"" ""
"" "" "" fn style (&self) -> Option<Style> { Some(self.0) }
},
Brace {
"" "" ""
"" ""
"" "" "" fn style (&self) -> Option<Style> { Some(self.0) }
},
LozengeDotted {
"" "" ""
"" ""
"" "" "" fn style (&self) -> Option<Style> { Some(self.0) }
},
Quarter {
"" "" "🮇"
"" "🮇"
"" "" "🮇" fn style (&self) -> Option<Style> { Some(self.0) }
},
QuarterV {
"" "" "🮇"
"" "🮇"
"" "" "🮇" fn style (&self) -> Option<Style> { Some(self.0) }
},
Chamfer {
"🭂" "" "🭍"
"" "🮇"
"🭓" "" "🭞" fn style (&self) -> Option<Style> { Some(self.0) }
},
Corners {
"🬆" "" "🬊" // 🬴 🬸
"" ""
"🬱" "" "🬵" fn style (&self) -> Option<Style> { Some(self.0) }
},
CornersTall {
"🭽" "" "🭾"
"" ""
"🭼" "" "🭿" fn style (&self) -> Option<Style> { Some(self.0) }
}
}
pub const CORNERS: CornersTall = CornersTall(Style {
fg: Some(Color::Rgb(96, 255, 32)),
bg: None,
underline_color: None,
add_modifier: Modifier::empty(),
sub_modifier: Modifier::DIM
});
//pub trait TuiStyle: Render<Tui> + Sized {
//fn fg (self, color: Color) -> impl Render<Tui> {
//Layers::new(move |add|{ add(&Foreground(color))?; add(&self) })