mirror of
https://codeberg.org/unspeaker/tengri.git
synced 2026-02-21 10:39:03 +01:00
wip: refactor(tui): 1 error left
how do i flip buffer
This commit is contained in:
parent
3bdef228e8
commit
8ca90b9aa0
5 changed files with 86 additions and 58 deletions
|
|
@ -64,8 +64,8 @@ impl<N: Coord> XYWH<N> {
|
||||||
pub fn with_h (&self, h: N) -> XYWH<N> {
|
pub fn with_h (&self, h: N) -> XYWH<N> {
|
||||||
Self(self.x(), self.y(), self.w(), h)
|
Self(self.x(), self.y(), self.w(), h)
|
||||||
}
|
}
|
||||||
pub fn lrtb (&self) -> XYWH<N> {
|
pub fn lrtb (&self) -> [N;4] {
|
||||||
Self(self.x(), self.x2(), self.y(), self.y2())
|
[self.x(), self.x2(), self.y(), self.y2()]
|
||||||
}
|
}
|
||||||
pub fn clipped_w (&self, w: N) -> XYWH<N> {
|
pub fn clipped_w (&self, w: N) -> XYWH<N> {
|
||||||
Self(self.x(), self.y(), self.w().min(w), self.h())
|
Self(self.x(), self.y(), self.w().min(w), self.h())
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#![feature(type_changing_struct_update, trait_alias)]
|
#![feature(type_changing_struct_update, trait_alias)]
|
||||||
|
|
||||||
use std::{time::Duration, thread::{spawn, JoinHandle}};
|
use std::{time::Duration, thread::{spawn, JoinHandle}, io::Write};
|
||||||
|
|
||||||
use unicode_width::*;
|
use unicode_width::*;
|
||||||
|
|
||||||
pub use ::{
|
pub use ::{
|
||||||
|
|
@ -86,7 +85,9 @@ mod tui_traits; pub use self::tui_traits::*;
|
||||||
mod tui_impls; pub use self::tui_impls::*;
|
mod tui_impls; pub use self::tui_impls::*;
|
||||||
|
|
||||||
/// Run an app in the main loop.
|
/// Run an app in the main loop.
|
||||||
pub fn tui_run <T>(state: &Arc<RwLock<T>>) -> Usually<Arc<RwLock<Tui>>> {
|
pub fn tui_run <T: Send + Sync + Draw<TuiOut> + Handle<TuiIn> + 'static> (
|
||||||
|
state: &Arc<RwLock<T>>
|
||||||
|
) -> Usually<Arc<RwLock<Tui>>> {
|
||||||
let backend = CrosstermBackend::new(stdout());
|
let backend = CrosstermBackend::new(stdout());
|
||||||
let Size { width, height } = backend.size()?;
|
let Size { width, height } = backend.size()?;
|
||||||
let tui = Arc::new(RwLock::new(Tui {
|
let tui = Arc::new(RwLock::new(Tui {
|
||||||
|
|
@ -96,9 +97,9 @@ pub fn tui_run <T>(state: &Arc<RwLock<T>>) -> Usually<Arc<RwLock<Tui>>> {
|
||||||
perf: Default::default(),
|
perf: Default::default(),
|
||||||
backend,
|
backend,
|
||||||
}));
|
}));
|
||||||
let _input_thread = tui_input(tui, state, Duration::from_millis(100));
|
let _input_thread = tui_input(tui.clone(), state, Duration::from_millis(100));
|
||||||
tui.write().unwrap().setup()?;
|
tui.write().unwrap().setup()?;
|
||||||
let render_thread = tui_output(tui, state, Duration::from_millis(10))?;
|
let render_thread = tui_output(tui.clone(), state, Duration::from_millis(10))?;
|
||||||
match render_thread.join() {
|
match render_thread.join() {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
tui.write().unwrap().teardown()?;
|
tui.write().unwrap().teardown()?;
|
||||||
|
|
@ -112,7 +113,9 @@ pub fn tui_run <T>(state: &Arc<RwLock<T>>) -> Usually<Arc<RwLock<Tui>>> {
|
||||||
Ok(tui)
|
Ok(tui)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tui_setup (backend: &mut CrosstermBackend) -> Usually<()> {
|
pub fn tui_setup <W: Write> (
|
||||||
|
backend: &mut CrosstermBackend<W>
|
||||||
|
) -> Usually<()> {
|
||||||
let better_panic_handler = Settings::auto().verbosity(Verbosity::Full).create_panic_handler();
|
let better_panic_handler = Settings::auto().verbosity(Verbosity::Full).create_panic_handler();
|
||||||
std::panic::set_hook(Box::new(move |info: &std::panic::PanicHookInfo|{
|
std::panic::set_hook(Box::new(move |info: &std::panic::PanicHookInfo|{
|
||||||
stdout().execute(LeaveAlternateScreen).unwrap();
|
stdout().execute(LeaveAlternateScreen).unwrap();
|
||||||
|
|
@ -125,14 +128,14 @@ pub fn tui_setup (backend: &mut CrosstermBackend) -> Usually<()> {
|
||||||
enable_raw_mode().map_err(Into::into)
|
enable_raw_mode().map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tui_teardown (backend: &mut CrosstermBackend) -> Usually<()> {
|
pub fn tui_teardown <W: Write> (backend: &mut CrosstermBackend<W>) -> Usually<()> {
|
||||||
stdout().execute(LeaveAlternateScreen)?;
|
stdout().execute(LeaveAlternateScreen)?;
|
||||||
backend.show_cursor()?;
|
backend.show_cursor()?;
|
||||||
disable_raw_mode().map_err(Into::into)
|
disable_raw_mode().map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tui_resized (
|
pub fn tui_resized <W: Write> (
|
||||||
backend: &mut CrosstermBackend, buffer: &mut Buffer, size: ratatui::prelude::Rect
|
backend: &mut CrosstermBackend<W>, buffer: &mut Buffer, size: ratatui::prelude::Rect
|
||||||
) {
|
) {
|
||||||
if buffer.area != size {
|
if buffer.area != size {
|
||||||
backend.clear_region(ClearType::All).unwrap();
|
backend.clear_region(ClearType::All).unwrap();
|
||||||
|
|
@ -141,17 +144,21 @@ pub fn tui_resized (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tui_redrawn (
|
pub fn tui_redrawn <'b, W: Write> (
|
||||||
backend: &mut CrosstermBackend, buffer: &mut Buffer, new_buffer: &mut Buffer
|
backend: &mut CrosstermBackend<W>,
|
||||||
|
mut prev_buffer: &'b mut Buffer,
|
||||||
|
mut next_buffer: &'b mut Buffer
|
||||||
) {
|
) {
|
||||||
let updates = buffer.diff(&new_buffer);
|
let updates = prev_buffer.diff(&next_buffer);
|
||||||
backend.draw(updates.into_iter()).expect("failed to render");
|
backend.draw(updates.into_iter()).expect("failed to render");
|
||||||
backend.flush().expect("failed to flush output new_buffer");
|
Backend::flush(backend).expect("failed to flush output new_buffer");
|
||||||
std::mem::swap(&mut buffer, &mut new_buffer);
|
std::mem::swap(&mut prev_buffer, &mut next_buffer);
|
||||||
new_buffer.reset();
|
next_buffer.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tui_update (buf: &mut Buffer, area: XY<u16>, callback: &impl Fn(&mut Cell, u16, u16)) {
|
pub fn tui_update (
|
||||||
|
buf: &mut Buffer, area: XYWH<u16>, callback: &impl Fn(&mut Cell, u16, u16)
|
||||||
|
) {
|
||||||
for row in 0..area.h() {
|
for row in 0..area.h() {
|
||||||
let y = area.y() + row;
|
let y = area.y() + row;
|
||||||
for col in 0..area.w() {
|
for col in 0..area.w() {
|
||||||
|
|
@ -167,7 +174,7 @@ pub fn tui_update (buf: &mut Buffer, area: XY<u16>, callback: &impl Fn(&mut Cell
|
||||||
|
|
||||||
/// Spawn the output thread.
|
/// Spawn the output thread.
|
||||||
pub fn tui_output <T: Draw<TuiOut> + Send + Sync + 'static> (
|
pub fn tui_output <T: Draw<TuiOut> + Send + Sync + 'static> (
|
||||||
engine: &Arc<RwLock<Tui>>, state: &Arc<RwLock<T>>, timer: Duration
|
engine: Arc<RwLock<Tui>>, state: &Arc<RwLock<T>>, timer: Duration
|
||||||
) -> Result<JoinHandle<()>, std::io::Error> {
|
) -> Result<JoinHandle<()>, std::io::Error> {
|
||||||
let exited = engine.read().unwrap().exited.clone();
|
let exited = engine.read().unwrap().exited.clone();
|
||||||
let engine = engine.clone();
|
let engine = engine.clone();
|
||||||
|
|
@ -202,7 +209,7 @@ pub fn tui_output <T: Draw<TuiOut> + Send + Sync + 'static> (
|
||||||
|
|
||||||
/// Spawn the input thread.
|
/// Spawn the input thread.
|
||||||
pub fn tui_input <T: Handle<TuiIn> + Send + Sync + 'static> (
|
pub fn tui_input <T: Handle<TuiIn> + Send + Sync + 'static> (
|
||||||
engine: &Arc<RwLock<Tui>>, state: &Arc<RwLock<T>>, timer: Duration
|
engine: Arc<RwLock<Tui>>, state: &Arc<RwLock<T>>, timer: Duration
|
||||||
) -> JoinHandle<()> {
|
) -> JoinHandle<()> {
|
||||||
let exited = engine.read().unwrap().exited.clone();
|
let exited = engine.read().unwrap().exited.clone();
|
||||||
let state = state.clone();
|
let state = state.clone();
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,11 @@ use rand::{thread_rng, distributions::uniform::UniformSampler};
|
||||||
|
|
||||||
impl Tui {
|
impl Tui {
|
||||||
/// Create and launch a terminal user interface.
|
/// 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
|
/// True if done
|
||||||
pub fn exited (&self) -> bool { self.exited.fetch_and(true, Relaxed) }
|
pub fn exited (&self) -> bool { self.exited.fetch_and(true, Relaxed) }
|
||||||
/// Prepare before run
|
/// Prepare before run
|
||||||
|
|
@ -97,22 +101,22 @@ impl Out for TuiOut {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl TuiOut {
|
impl TuiOut {
|
||||||
#[inline] pub fn with_rect (&mut self, area: XY<u16>) -> &mut Self { self.area = area; self }
|
#[inline] pub fn with_rect (&mut self, area: XYWH<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 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: XY<u16>, c: char) { self.update(area, &|cell,_,_|{cell.set_char(c);}) }
|
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: XY<u16>, color: Color) { self.update(area, &|cell,_,_|{cell.set_bg(color);}) }
|
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: XY<u16>, color: Color) { self.update(area, &|cell,_,_|{cell.set_fg(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: XY<u16>, on: bool, modifier: Modifier) {
|
pub fn fill_mod (&mut self, area: XYWH<u16>, on: bool, modifier: Modifier) {
|
||||||
if on {
|
if on {
|
||||||
self.update(area, &|cell,_,_|cell.modifier.insert(modifier))
|
self.update(area, &|cell,_,_|cell.modifier.insert(modifier))
|
||||||
} else {
|
} else {
|
||||||
self.update(area, &|cell,_,_|cell.modifier.remove(modifier))
|
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_bold (&mut self, area: XYWH<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_reversed (&mut self, area: XYWH<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_crossed_out (&mut self, area: XYWH<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_ul (&mut self, area: XYWH<u16>, color: Option<Color>) {
|
||||||
if let Some(color) = color {
|
if let Some(color) = color {
|
||||||
self.update(area, &|cell,_,_|{
|
self.update(area, &|cell,_,_|{
|
||||||
cell.modifier.insert(ratatui::prelude::Modifier::UNDERLINED);
|
cell.modifier.insert(ratatui::prelude::Modifier::UNDERLINED);
|
||||||
|
|
@ -282,11 +286,11 @@ impl<T> Phat<T> {
|
||||||
pub const HI: &'static str = "▀";
|
pub const HI: &'static str = "▀";
|
||||||
/// A phat line
|
/// A phat line
|
||||||
pub fn lo (fg: Color, bg: Color) -> impl Content<TuiOut> {
|
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
|
/// A phat line
|
||||||
pub fn hi (fg: Color, bg: Color) -> impl Content<TuiOut> {
|
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 {
|
impl Scrollbar {
|
||||||
|
|
@ -350,14 +354,30 @@ mod layout {
|
||||||
impl<T: Content<TuiOut>> Layout<TuiOut> for Modify<T> {}
|
impl<T: Content<TuiOut>> Layout<TuiOut> for Modify<T> {}
|
||||||
impl<T: Content<TuiOut>> Layout<TuiOut> for Styled<T> {}
|
impl<T: Content<TuiOut>> Layout<TuiOut> for Styled<T> {}
|
||||||
impl Layout<TuiOut> for Repeat<'_> {}
|
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 &str {
|
||||||
impl Layout<TuiOut> for String { fn layout (&self, to: XY<u16>) -> XY<u16> { self.as_str().layout(to) } }
|
fn layout (&self, to: XYWH<u16>) -> XYWH<u16> {
|
||||||
impl Layout<TuiOut> for Arc<str> { fn layout (&self, to: XY<u16>) -> XY<u16> { self.as_ref().layout(to) } }
|
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> {
|
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> {
|
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<'_> {
|
impl Draw<TuiOut> for Repeat<'_> {
|
||||||
fn draw (&self, to: &mut TuiOut) {
|
fn draw (&self, to: &mut TuiOut) {
|
||||||
|
let XYWH(x, y, w, h) = to.area();
|
||||||
match self {
|
match self {
|
||||||
Self::X(c) => {
|
Self::X(c) => {
|
||||||
let [x, y, w, _h] = to.area().xywh();
|
|
||||||
for x in x..x+w {
|
for x in x..x+w {
|
||||||
if let Some(cell) = to.buffer.cell_mut(Position::from((x, y))) {
|
if let Some(cell) = to.buffer.cell_mut(Position::from((x, y))) {
|
||||||
cell.set_symbol(&c);
|
cell.set_symbol(&c);
|
||||||
|
|
@ -404,21 +424,19 @@ mod draw {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Self::Y(c) => {
|
Self::Y(c) => {
|
||||||
let [x, y, _w, h] = to.area().xywh();
|
|
||||||
for y in y..y+h {
|
for y in y..y+h {
|
||||||
if let Some(cell) = to.buffer.cell_mut(Position::from((x, y))) {
|
if let Some(cell) = to.buffer.cell_mut(Position::from((x, y))) {
|
||||||
cell.set_symbol(&c);
|
cell.set_symbol(&c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Self::XY => {
|
Self::XY(c) => {
|
||||||
let [x, y, w, h] = to.area().xywh();
|
let a = c.len();
|
||||||
let a = self.0.len();
|
|
||||||
for (_v, y) in (y..y+h).enumerate() {
|
for (_v, y) in (y..y+h).enumerate() {
|
||||||
for (u, x) in (x..x+w).enumerate() {
|
for (u, x) in (x..x+w).enumerate() {
|
||||||
if let Some(cell) = to.buffer.cell_mut(Position::from((x, y))) {
|
if let Some(cell) = to.buffer.cell_mut(Position::from((x, y))) {
|
||||||
let u = u % a;
|
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 {
|
impl Draw<TuiOut> for Scrollbar {
|
||||||
fn draw (&self, to: &mut TuiOut) {
|
fn draw (&self, to: &mut TuiOut) {
|
||||||
let [x1, y1, w, h] = to.area().xywh();
|
let XYWH(x1, y1, w, h) = to.area();
|
||||||
match self {
|
match self {
|
||||||
Self::X { .. } => {
|
Self::X { .. } => {
|
||||||
let x2 = x1 + w;
|
let x2 = x1 + w;
|
||||||
|
|
@ -439,10 +457,10 @@ mod draw {
|
||||||
cell.set_fg(Rgb(255, 255, 255));
|
cell.set_fg(Rgb(255, 255, 255));
|
||||||
cell.set_bg(Rgb(0, 0, 0));
|
cell.set_bg(Rgb(0, 0, 0));
|
||||||
cell.set_char(Self::ICON_DEC_H[i as usize]);
|
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_fg(Rgb(255, 255, 255));
|
||||||
cell.set_bg(Rgb(0, 0, 0));
|
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 {
|
} else if false {
|
||||||
cell.set_fg(Rgb(255, 255, 255));
|
cell.set_fg(Rgb(255, 255, 255));
|
||||||
cell.set_bg(Reset);
|
cell.set_bg(Reset);
|
||||||
|
|
@ -462,11 +480,11 @@ mod draw {
|
||||||
if (i as usize) < (Self::ICON_DEC_V.len()) {
|
if (i as usize) < (Self::ICON_DEC_V.len()) {
|
||||||
cell.set_fg(Rgb(255, 255, 255));
|
cell.set_fg(Rgb(255, 255, 255));
|
||||||
cell.set_bg(Rgb(0, 0, 0));
|
cell.set_bg(Rgb(0, 0, 0));
|
||||||
cell.set_char(Self::ICON_DEC_v[i as usize]);
|
cell.set_char(Self::ICON_DEC_V[i as usize]);
|
||||||
} else if (i as usize) > (h as usize - Self::ICON_INC.len()) {
|
} else if (i as usize) > (h as usize - Self::ICON_INC_V.len()) {
|
||||||
cell.set_fg(Rgb(255, 255, 255));
|
cell.set_fg(Rgb(255, 255, 255));
|
||||||
cell.set_bg(Rgb(0, 0, 0));
|
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 {
|
} else if false {
|
||||||
cell.set_fg(Rgb(255, 255, 255));
|
cell.set_fg(Rgb(255, 255, 255));
|
||||||
cell.set_bg(Reset);
|
cell.set_bg(Reset);
|
||||||
|
|
@ -485,7 +503,7 @@ mod draw {
|
||||||
|
|
||||||
impl Draw<TuiOut> for &str {
|
impl Draw<TuiOut> for &str {
|
||||||
fn draw (&self, to: &mut TuiOut) {
|
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)
|
to.text(&self, x, y, w)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,10 @@ pub struct Tui {
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd)] pub struct TuiEvent(pub Event);
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd)] pub struct TuiEvent(pub Event);
|
||||||
|
|
||||||
pub struct TuiKey(Option<KeyCode>, KeyModifiers);
|
#[derive(Debug, Clone, Eq, PartialEq, PartialOrd)] pub struct TuiKey(
|
||||||
|
pub Option<KeyCode>,
|
||||||
|
pub KeyModifiers
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(Default)] pub struct TuiOut {
|
#[derive(Default)] pub struct TuiOut {
|
||||||
pub buffer: Buffer,
|
pub buffer: Buffer,
|
||||||
|
|
@ -68,8 +71,8 @@ pub struct TrimStringRef<'a, T: AsRef<str>>(pub u16, pub &'a T);
|
||||||
|
|
||||||
/// Thunks can be natural error boundaries!
|
/// Thunks can be natural error boundaries!
|
||||||
pub struct ErrorBoundary<O: Out, T: Draw<O>>(
|
pub struct ErrorBoundary<O: Out, T: Draw<O>>(
|
||||||
std::marker::PhantomData<O>,
|
pub std::marker::PhantomData<O>,
|
||||||
Perhaps<T>
|
pub Perhaps<T>
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Repeat a string, e.g. for background
|
/// Repeat a string, e.g. for background
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@ pub trait BorderStyle: Content<TuiOut> + Copy {
|
||||||
}
|
}
|
||||||
#[inline] fn draw_horizontal (
|
#[inline] fn draw_horizontal (
|
||||||
&self, to: &mut TuiOut, style: Option<Style>
|
&self, to: &mut TuiOut, style: Option<Style>
|
||||||
) -> Usually<[u16;4]> {
|
) -> Usually<XYWH<u16>> {
|
||||||
let area = to.area();
|
let area = to.area();
|
||||||
let style = style.or_else(||self.style_horizontal());
|
let style = style.or_else(||self.style_horizontal());
|
||||||
let [x, x2, y, y2] = area.lrtb();
|
let [x, x2, y, y2] = area.lrtb();
|
||||||
|
|
@ -70,7 +70,7 @@ pub trait BorderStyle: Content<TuiOut> + Copy {
|
||||||
}
|
}
|
||||||
#[inline] fn draw_vertical (
|
#[inline] fn draw_vertical (
|
||||||
&self, to: &mut TuiOut, style: Option<Style>
|
&self, to: &mut TuiOut, style: Option<Style>
|
||||||
) -> Usually<[u16;4]> {
|
) -> Usually<XYWH<u16>> {
|
||||||
let area = to.area();
|
let area = to.area();
|
||||||
let style = style.or_else(||self.style_vertical());
|
let style = style.or_else(||self.style_vertical());
|
||||||
let [x, x2, y, y2] = area.lrtb();
|
let [x, x2, y, y2] = area.lrtb();
|
||||||
|
|
@ -88,10 +88,10 @@ pub trait BorderStyle: Content<TuiOut> + Copy {
|
||||||
}
|
}
|
||||||
#[inline] fn draw_corners (
|
#[inline] fn draw_corners (
|
||||||
&self, to: &mut TuiOut, style: Option<Style>
|
&self, to: &mut TuiOut, style: Option<Style>
|
||||||
) -> Usually<[u16;4]> {
|
) -> Usually<XYWH<u16>> {
|
||||||
let area = to.area();
|
let area = to.area();
|
||||||
let style = style.or_else(||self.style_corners());
|
let style = style.or_else(||self.style_corners());
|
||||||
let [x, y, width, height] = area.xywh();
|
let XYWH(x, y, width, height) = area;
|
||||||
if width > 1 && height > 1 {
|
if width > 1 && height > 1 {
|
||||||
to.blit(&Self::NW, x, y, style);
|
to.blit(&Self::NW, x, y, style);
|
||||||
to.blit(&Self::NE, x + width - 1, y, style);
|
to.blit(&Self::NE, x + width - 1, y, style);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue