Dx tired. new repo with a baseline

daddy
elfein727 2021-12-11 20:32:38 -08:00
parent c3070c3b69
commit f1ddb696e6
7 changed files with 205 additions and 0 deletions

9
Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "tuid"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
crossterm = "0.22.1"

55
src/lib.rs Normal file
View File

@ -0,0 +1,55 @@
use crossterm::{
cursor, queue,
style::{self, Stylize},
terminal::{Clear, ClearType, size},
ExecutableCommand, QueueableCommand, Result as CTRes,
};
use std::io::{stdout, Stdout, Write};
use std::sync::Arc;
mod widget;
use widget::*;
pub struct Size {
a: usize,
b: usize,
}
impl From<(u16, u16)> for Size {
fn from(s: (u16, u16)) -> Self {
Self {
a: s.0 as usize,
b: s.1 as usize,
}
}
}
pub struct Point {
a: usize,
b: usize,
}
pub trait Data {}
impl<T> Data for Arc<T> {}
struct Window<'a, T: Data> {
out: Stdout,
root_widget: Box<&'a dyn Widget<T>>,
}
impl<'a, T: Data> Window<'a, T> {
pub fn new(widget: &'a dyn Widget<T>) -> Self {
Self {
out: stdout(),
root_widget: Box::new(widget),
}
}
pub fn draw(&mut self) -> CTRes<()> {
queue![self.out, Clear(ClearType::All)]?;
let terminal_size = size();
self.root_widget.layout(terminal_size.into());
self.out.flush();
Ok(())
}
}

41
src/widget/flex.rs Normal file
View File

@ -0,0 +1,41 @@
use crate::{Data, Size, Widget};
use super::WidgetPod;
enum Direction {
Vertical,
Horizont,
}
pub struct Flex<T> {
children: Vec<WidgetPod<T, Box<dyn Widget<T>>>>,
}
impl<T: Data> Flex<T> {
pub fn new() -> Self {
Self { children: vec![] }
}
pub fn with_child(mut self, child: impl Widget<T> + 'static) -> Self {
self.children.push(WidgetPod::new(Box::new(child)));
self
}
}
impl<T: Data> Widget<T> for Flex<T> {
fn layout(&mut self, bounds: &Size) -> Size {
let mut output = Size { a: 0, b: 0 };
for child in &mut self.children {
if output.a + child.layout(bounds).a < bounds.a {
output.a += child.layout(bounds).a;
output.b = child.layout(bounds).b.max(output.b);
} else {
output.a = child.layout(bounds).a.max(output.a);
output.b += child.layout(bounds).b;
}
}
output
}
fn paint(&self, buf: &mut [&mut [char]]) {}
}

8
src/widget/mod.rs Normal file
View File

@ -0,0 +1,8 @@
mod flex;
mod text;
mod widget;
mod widget_pod;
pub use flex::*;
pub use text::*;
pub use widget::*;
pub use widget_pod::*;

39
src/widget/text.rs Normal file
View File

@ -0,0 +1,39 @@
use crate::{Data, Size, Widget};
pub struct Text<T: Data> {
data: T,
text: Box<dyn Fn(&T) -> String>,
}
impl<T: Data> Text<T> {
pub fn new(data: T, text: Box<dyn Fn(&T) -> String>) -> Self {
Self { data, text }
}
fn text(&self) -> String {
(self.text)(&self.data)
}
}
impl<T: Data> Widget<T> for Text<T> {
fn layout(&mut self, _bounds: &Size) -> Size {
Size {
a: self.text().chars().count(),
b: self.text().chars().filter(|ch| *ch == '\n').count(),
}
}
fn paint(&self, buf: &mut [&mut [char]]) {
let the_text = self.text();
let mut the_chars = the_text.chars();
for line in buf.iter_mut() {
for spot in line.iter_mut() {
if let Some(ch) = the_chars.next() {
if ch == '\n' {
break;
} else {
*spot = ch;
}
}
}
}
}
}

18
src/widget/widget.rs Normal file
View File

@ -0,0 +1,18 @@
use std::ops::{DerefMut, Deref};
use crate::Size;
pub trait Widget<T> {
fn layout(&mut self, bounds: &Size) -> Size;
fn paint(&self, buf: &mut [&mut [char]]);
}
impl<T> Widget<T> for Box<dyn Widget<T>> {
fn layout(&mut self, bounds: &Size) -> Size {
self.deref_mut().layout(bounds)
}
fn paint(&self, buf: &mut [&mut [char]]) {
self.deref().paint(buf)
}
}

35
src/widget/widget_pod.rs Normal file
View File

@ -0,0 +1,35 @@
use std::marker::PhantomData;
use crate::{Point, Widget, Size, Data};
pub struct WidgetPod<T, W> {
data: PhantomData<T>,
inner: W,
origin: Point,
}
impl<T, W: Widget<T>> WidgetPod<T, W> {
pub fn new(inner: W) -> Self {
Self {
data: PhantomData,
inner,
origin: Point { a: 0, b: 0 },
}
}
pub fn set_origin(&mut self, p: Point) {
self.origin = p;
}
}
impl<T: Data, W: Widget<T>> Widget<T> for WidgetPod<T, W> {
fn layout(&mut self, bounds: &Size) -> Size {
self.inner.layout(bounds)
}
fn paint(&self, buf: &mut [&mut [char]]) {
self.inner.paint(buf)
}
}