wip: refactor(tui): 1 error left

how do i flip buffer
This commit is contained in:
same mf who else 2026-02-20 00:28:56 +02:00
parent 3bdef228e8
commit 8ca90b9aa0
5 changed files with 86 additions and 58 deletions

View file

@ -4,7 +4,11 @@ use rand::{thread_rng, distributions::uniform::UniformSampler};
impl Tui {
/// Create and launch a terminal user interface.
pub fn run <T> (state: &Arc<RwLock<T>>) -> Usually<Arc<RwLock<Self>>> { tui_run(state) }
pub fn run <T: Send + Sync + Handle<TuiIn> + Draw<TuiOut> + 'static> (
state: &Arc<RwLock<T>>
) -> Usually<Arc<RwLock<Self>>> {
tui_run(state)
}
/// True if done
pub fn exited (&self) -> bool { self.exited.fetch_and(true, Relaxed) }
/// Prepare before run
@ -97,22 +101,22 @@ impl Out for TuiOut {
}
}
impl TuiOut {
#[inline] pub fn with_rect (&mut self, area: XY<u16>) -> &mut Self { self.area = area; self }
pub fn update (&mut self, area: XY<u16>, callback: &impl Fn(&mut Cell, u16, u16)) { tui_update(&mut self.buffer, area, callback); }
pub fn fill_char (&mut self, area: XY<u16>, c: char) { self.update(area, &|cell,_,_|{cell.set_char(c);}) }
pub fn fill_bg (&mut self, area: XY<u16>, color: Color) { self.update(area, &|cell,_,_|{cell.set_bg(color);}) }
pub fn fill_fg (&mut self, area: XY<u16>, color: Color) { self.update(area, &|cell,_,_|{cell.set_fg(color);}) }
pub fn fill_mod (&mut self, area: XY<u16>, on: bool, modifier: Modifier) {
#[inline] pub fn with_rect (&mut self, area: XYWH<u16>) -> &mut Self { self.area = area; self }
pub fn update (&mut self, area: XYWH<u16>, callback: &impl Fn(&mut Cell, u16, u16)) { tui_update(&mut self.buffer, area, callback); }
pub fn fill_char (&mut self, area: XYWH<u16>, c: char) { self.update(area, &|cell,_,_|{cell.set_char(c);}) }
pub fn fill_bg (&mut self, area: XYWH<u16>, color: Color) { self.update(area, &|cell,_,_|{cell.set_bg(color);}) }
pub fn fill_fg (&mut self, area: XYWH<u16>, color: Color) { self.update(area, &|cell,_,_|{cell.set_fg(color);}) }
pub fn fill_mod (&mut self, area: XYWH<u16>, on: bool, modifier: Modifier) {
if on {
self.update(area, &|cell,_,_|cell.modifier.insert(modifier))
} else {
self.update(area, &|cell,_,_|cell.modifier.remove(modifier))
}
}
pub fn fill_bold (&mut self, area: XY<u16>, on: bool) { self.fill_mod(area, on, Modifier::BOLD) }
pub fn fill_reversed (&mut self, area: XY<u16>, on: bool) { self.fill_mod(area, on, Modifier::REVERSED) }
pub fn fill_crossed_out (&mut self, area: XY<u16>, on: bool) { self.fill_mod(area, on, Modifier::CROSSED_OUT) }
pub fn fill_ul (&mut self, area: XY<u16>, color: Option<Color>) {
pub fn fill_bold (&mut self, area: XYWH<u16>, on: bool) { self.fill_mod(area, on, Modifier::BOLD) }
pub fn fill_reversed (&mut self, area: XYWH<u16>, on: bool) { self.fill_mod(area, on, Modifier::REVERSED) }
pub fn fill_crossed_out (&mut self, area: XYWH<u16>, on: bool) { self.fill_mod(area, on, Modifier::CROSSED_OUT) }
pub fn fill_ul (&mut self, area: XYWH<u16>, color: Option<Color>) {
if let Some(color) = color {
self.update(area, &|cell,_,_|{
cell.modifier.insert(ratatui::prelude::Modifier::UNDERLINED);
@ -282,11 +286,11 @@ impl<T> Phat<T> {
pub const HI: &'static str = "";
/// A phat line
pub fn lo (fg: Color, bg: Color) -> impl Content<TuiOut> {
Fixed::Y(1, Tui::fg_bg(fg, bg, RepeatH(Self::LO)))
Fixed::Y(1, Tui::fg_bg(fg, bg, Repeat::X(Self::LO)))
}
/// A phat line
pub fn hi (fg: Color, bg: Color) -> impl Content<TuiOut> {
Fixed::Y(1, Tui::fg_bg(fg, bg, RepeatH(Self::HI)))
Fixed::Y(1, Tui::fg_bg(fg, bg, Repeat::X(Self::HI)))
}
}
impl Scrollbar {
@ -350,14 +354,30 @@ mod layout {
impl<T: Content<TuiOut>> Layout<TuiOut> for Modify<T> {}
impl<T: Content<TuiOut>> Layout<TuiOut> for Styled<T> {}
impl Layout<TuiOut> for Repeat<'_> {}
impl Layout<TuiOut> for &str { fn layout (&self, to: XY<u16>) -> XY<u16> { to.center_xy([width_chars_max(to.w(), self), 1]) } }
impl Layout<TuiOut> for String { fn layout (&self, to: XY<u16>) -> XY<u16> { self.as_str().layout(to) } }
impl Layout<TuiOut> for Arc<str> { fn layout (&self, to: XY<u16>) -> XY<u16> { self.as_ref().layout(to) } }
impl Layout<TuiOut> for &str {
fn layout (&self, to: XYWH<u16>) -> XYWH<u16> {
to.centered_xy([width_chars_max(to.w(), self), 1])
}
}
impl Layout<TuiOut> for String {
fn layout (&self, to: XYWH<u16>) -> XYWH<u16> {
self.as_str().layout(to)
}
}
impl Layout<TuiOut> for Arc<str> {
fn layout (&self, to: XYWH<u16>) -> XYWH<u16> {
self.as_ref().layout(to)
}
}
impl<'a, T: AsRef<str>> Layout<TuiOut> for TrimString<T> {
fn layout (&self, to: XY<u16>) -> XY<u16> { Layout::layout(&self.as_ref(), to) }
fn layout (&self, to: XYWH<u16>) -> XYWH<u16> {
Layout::layout(&self.as_ref(), to)
}
}
impl<'a, T: AsRef<str>> Layout<TuiOut> for TrimStringRef<'a, T> {
fn layout (&self, to: XY<u16>) -> XY<u16> { [to.x(), to.y(), to.w().min(self.0).min(self.1.as_ref().width() as u16), to.h()] }
fn layout (&self, to: XYWH<u16>) -> XYWH<u16> {
XYWH(to.x(), to.y(), to.w().min(self.0).min(self.1.as_ref().width() as u16), to.h())
}
}
}
@ -394,9 +414,9 @@ mod draw {
impl Draw<TuiOut> for Repeat<'_> {
fn draw (&self, to: &mut TuiOut) {
let XYWH(x, y, w, h) = to.area();
match self {
Self::X(c) => {
let [x, y, w, _h] = to.area().xywh();
for x in x..x+w {
if let Some(cell) = to.buffer.cell_mut(Position::from((x, y))) {
cell.set_symbol(&c);
@ -404,21 +424,19 @@ mod draw {
}
},
Self::Y(c) => {
let [x, y, _w, h] = to.area().xywh();
for y in y..y+h {
if let Some(cell) = to.buffer.cell_mut(Position::from((x, y))) {
cell.set_symbol(&c);
}
}
},
Self::XY => {
let [x, y, w, h] = to.area().xywh();
let a = self.0.len();
Self::XY(c) => {
let a = c.len();
for (_v, y) in (y..y+h).enumerate() {
for (u, x) in (x..x+w).enumerate() {
if let Some(cell) = to.buffer.cell_mut(Position::from((x, y))) {
let u = u % a;
cell.set_symbol(&self.0[u..u+1]);
cell.set_symbol(&c[u..u+1]);
}
}
}
@ -429,7 +447,7 @@ mod draw {
impl Draw<TuiOut> for Scrollbar {
fn draw (&self, to: &mut TuiOut) {
let [x1, y1, w, h] = to.area().xywh();
let XYWH(x1, y1, w, h) = to.area();
match self {
Self::X { .. } => {
let x2 = x1 + w;
@ -439,10 +457,10 @@ mod draw {
cell.set_fg(Rgb(255, 255, 255));
cell.set_bg(Rgb(0, 0, 0));
cell.set_char(Self::ICON_DEC_H[i as usize]);
} else if i > (w as usize - Self::ICON_INC.len()) {
} else if i > (w as usize - Self::ICON_INC_H.len()) {
cell.set_fg(Rgb(255, 255, 255));
cell.set_bg(Rgb(0, 0, 0));
cell.set_char(Self::ICON_INC[w as usize - i]);
cell.set_char(Self::ICON_INC_H[w as usize - i]);
} else if false {
cell.set_fg(Rgb(255, 255, 255));
cell.set_bg(Reset);
@ -462,11 +480,11 @@ mod draw {
if (i as usize) < (Self::ICON_DEC_V.len()) {
cell.set_fg(Rgb(255, 255, 255));
cell.set_bg(Rgb(0, 0, 0));
cell.set_char(Self::ICON_DEC_v[i as usize]);
} else if (i as usize) > (h as usize - Self::ICON_INC.len()) {
cell.set_char(Self::ICON_DEC_V[i as usize]);
} else if (i as usize) > (h as usize - Self::ICON_INC_V.len()) {
cell.set_fg(Rgb(255, 255, 255));
cell.set_bg(Rgb(0, 0, 0));
cell.set_char(Self::ICON_INC[h as usize - i]);
cell.set_char(Self::ICON_INC_V[h as usize - i]);
} else if false {
cell.set_fg(Rgb(255, 255, 255));
cell.set_bg(Reset);
@ -485,7 +503,7 @@ mod draw {
impl Draw<TuiOut> for &str {
fn draw (&self, to: &mut TuiOut) {
let [x, y, w, ..] = self.layout(to.area());
let XYWH(x, y, w, ..) = self.layout(to.area());
to.text(&self, x, y, w)
}
}