From dac3acdceb0c8c80427f7234e5314c573922f879 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Fri, 27 Dec 2024 11:03:54 -0600 Subject: [PATCH 1/2] writer-rewrite 01 --- src/lib.rs | 37 ++++++++++++++++++++++--------------- src/main.rs | 13 +++++-------- src/ui/styles.rs | 9 ++++++++- src/utils.rs | 38 +++++++++++++++++++------------------- 4 files changed, 54 insertions(+), 43 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 1501ee8..00d6e98 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -117,7 +117,7 @@ pub struct Writer { style: ui::StyleElement, focused: bool, size: (u16, u16), - absolute: (u16, u16), + pos: (u16, u16), written: (u16, u16), } @@ -178,7 +178,14 @@ impl Document { pub fn render(&self) { if !self.element.is_null() { let (width, height) = crossterm::terminal::size().unwrap(); - let mut frame = utils::Frame::new((0, 0), (width, height), &self.css); + let mut writer = Writer::new( + true, + ui::StyleElement::default(), + (0, 0), + (width, height), + &self.css, + ); + let mut frame = writer.new_frame(); utils::clear(); frame.render(true, unsafe { &*self.element }); utils::flush(); @@ -348,7 +355,7 @@ impl Writer { pub fn new( focused: bool, style: ui::StyleElement, - absolute: (u16, u16), + pos: (u16, u16), size: (u16, u16), css: &ui::Css, ) -> Writer { @@ -357,7 +364,7 @@ impl Writer { style, focused, size, - absolute, + pos, written: (0, 0), } } @@ -368,15 +375,15 @@ impl Writer { if self.style.outline.1 { print!( "\x1B[{};{}H{outline_ch}{}", - self.absolute.1 + 2 + i as u16, - self.absolute.0 + 1, + self.pos.1 + 2 + i as u16, + self.pos.0 + 1, self.style.write(line), ); } else { print!( "\x1B[{};{}H{}", - self.absolute.1 + 1 + i as u16, - self.absolute.0 + 1, + self.pos.1 + 1 + i as u16, + self.pos.0 + 1, self.style.write(line) ); } @@ -390,8 +397,8 @@ impl Writer { if self.style.outline.1 { print!( "\x1B[{};{}H{}", - self.absolute.1 + 1, - self.absolute.0 + 1, + self.pos.1 + 1, + self.pos.0 + 1, self.style.write_outline(&format!( "╭{}╮", "─".repeat(self.get_size_root().0 as usize) @@ -399,8 +406,8 @@ impl Writer { ); print!( "\x1B[{};{}H{}", - self.absolute.1 + self.written.1 + 2, - self.absolute.0 + 1, + self.pos.1 + self.written.1 + 2, + self.pos.0 + 1, self.style.write_outline(&format!( "╰{}╯", "─".repeat(self.get_size_root().0 as usize) @@ -410,8 +417,8 @@ impl Writer { for i in 0..self.written.1 { print!( "\x1B[{};{}H{outline_ch}", - self.absolute.1 + i + 2, - self.absolute.0 + self.get_size_root().0 + 2, + self.pos.1 + i + 2, + self.pos.0 + self.get_size_root().0 + 2, ); } } @@ -448,7 +455,7 @@ impl Writer { } pub fn new_frame(&mut self) -> crate::utils::Frame { - crate::utils::Frame::new(self.absolute, self.get_size(), unsafe { &*self.css }) + crate::utils::Frame::new(self, unsafe { &*self.css }) } pub fn caret(&self) -> String { diff --git a/src/main.rs b/src/main.rs index 2349358..aabe9dd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,13 +6,10 @@ fn main() { #[component] pub fn App() { - rsx! { - async { - sleep(3000); - ersx!(text { - "OK" - }) - } - text { "Hello world!" } + ersx! { + text { style: style! { + x: 30 px, + y: 4 px + }, "hello, world" } } } diff --git a/src/ui/styles.rs b/src/ui/styles.rs index 8a00e89..02fceaa 100644 --- a/src/ui/styles.rs +++ b/src/ui/styles.rs @@ -329,7 +329,7 @@ impl Number { self.as_size_raw(frame_size) } } - pub fn as_position(&self, used: &u16, frame_size: u16) -> u16 { + pub fn as_position_raw(&self, used: &u16, frame_size: u16) -> u16 { match self { crate::ui::Number::Px(px) => *px, crate::ui::Number::Pe(pe) => (frame_size * pe) / 100, @@ -337,4 +337,11 @@ impl Number { crate::ui::Number::Auto => *used, } } + pub fn as_position(&self, outline: bool, used: &u16, frame_size: u16) -> u16 { + if outline { + self.as_position_raw(used, frame_size) + 1 + } else { + self.as_position_raw(used, frame_size) + } + } } diff --git a/src/utils.rs b/src/utils.rs index 549f584..d77f4f6 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,25 +1,17 @@ use std::io::{stdout, Write}; -use crate::ui; - pub struct Frame<'a> { used: Vec, - width: u16, - height: u16, - x: u16, - y: u16, - css: &'a ui::Css, + css: &'a crate::ui::Css, + writer: &'a mut crate::Writer, } impl<'a> Frame<'a> { - pub fn new((x, y): (u16, u16), (width, height): (u16, u16), css: &'a crate::ui::Css) -> Self { + pub fn new(writer: &'a mut crate::Writer, css: &'a crate::ui::Css) -> Self { Frame { - used: vec![0; height as usize], - width, - height, - x, - y, + used: vec![0; writer.size.1 as usize], css, + writer, } } pub fn render(&mut self, focused: bool, element: &crate::Element) { @@ -27,11 +19,14 @@ impl<'a> Frame<'a> { let mut style_element = style.clone().get(focused); for class in element.get_class().split(" ") { - if let Some(upper) = self.css.get(&ui::StyleName::Class(class.to_string())) { + if let Some(upper) = self + .css + .get(&crate::ui::StyleName::Class(class.to_string())) + { style_element.merge(upper); } - if let Some(upper) = self.css.get(&ui::StyleName::ClassState( + if let Some(upper) = self.css.get(&crate::ui::StyleName::ClassState( class.to_string(), if style.2 == "" && focused { "hover".to_string() @@ -45,6 +40,7 @@ impl<'a> Frame<'a> { if style_element.visible.1 { let y = style_element.y.1.as_position( + style_element.outline.1, &{ let mut y = 0; while y < self.used.len() && self.used[y] != 0 { @@ -52,15 +48,19 @@ impl<'a> Frame<'a> { } y as u16 }, - self.height, + self.writer.size.1, ); if let Some(y_) = self.used.get(y as usize) { - let x = style_element.x.1.as_position(y_, self.width); + let x = + style_element + .x + .1 + .as_position(style_element.outline.1, y_, self.writer.size.0); let mut writer = crate::Writer::new( focused, style_element.clone(), - (x + self.x, y + self.y), - (self.width, self.height), + (x, y), + self.writer.size, self.css, ); element.render(&mut writer); From 2cc029df91da93386ee5814cff2f4660b1134689 Mon Sep 17 00:00:00 2001 From: Leo dev Date: Sat, 28 Dec 2024 06:34:12 -0600 Subject: [PATCH 2/2] added outline support (still not done yet) --- src/lib.rs | 151 ++++++++++++++++++++++++++--------------------- src/main.rs | 14 +++-- src/ui/styles.rs | 6 +- src/utils.rs | 46 +++++++++------ 4 files changed, 127 insertions(+), 90 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 00d6e98..78f0c6b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -119,6 +119,7 @@ pub struct Writer { size: (u16, u16), pos: (u16, u16), written: (u16, u16), + parent: Option<*mut Writer>, } pub struct State(Arc>); @@ -178,16 +179,22 @@ impl Document { pub fn render(&self) { if !self.element.is_null() { let (width, height) = crossterm::terminal::size().unwrap(); - let mut writer = Writer::new( - true, - ui::StyleElement::default(), - (0, 0), - (width, height), - &self.css, - ); + let mut writer = Writer { + css: &self.css, + focused: true, + style: ui::StyleElement { + // outline: (true, true), + ..Default::default() + }, + size: (width, height), + pos: (1, 1), + written: (0, 0), + parent: None, + }; let mut frame = writer.new_frame(); utils::clear(); frame.render(true, unsafe { &*self.element }); + writer.after_render(width, height); utils::flush(); } } @@ -352,73 +359,83 @@ impl Handler { } impl Writer { - pub fn new( - focused: bool, - style: ui::StyleElement, - pos: (u16, u16), - size: (u16, u16), - css: &ui::Css, - ) -> Writer { - Writer { - css, - style, - focused, - size, - pos, - written: (0, 0), + pub fn after_render(&self, width: u16, height: u16) { + if self.style.outline.1 { + let ol = self.style.write_outline("│"); + let hl = "─".repeat(width as usize - 2); + self.write_abs_outline(&self.style.write_outline(&format!("╭{}╮", hl)), (0, 0)); + for i in 1..height { + self.write_abs_outline(&ol, (0, i)); + self.write_abs_outline(&ol, (width - 1, i)); + } + self.write_abs_outline(&self.style.write_outline(&format!("╰{}╯", hl)), (0, height)); } } pub fn write(&mut self, s: &str) { - let outline_ch = self.style.write_outline("│"); - for (i, line) in s.lines().enumerate() { - if self.style.outline.1 { - print!( - "\x1B[{};{}H{outline_ch}{}", - self.pos.1 + 2 + i as u16, - self.pos.0 + 1, - self.style.write(line), - ); - } else { - print!( - "\x1B[{};{}H{}", - self.pos.1 + 1 + i as u16, - self.pos.0 + 1, - self.style.write(line) - ); - } - let line_len = line.len() as u16; - if line_len > self.written.0 { - self.written.0 = line_len; - } - self.written.1 += 1; + // let width = self.get_size().0 as usize; + // let s = s + // .lines() + // .map(|l| { + // if l.len() > width { + // l.chars().take(width).collect::() + // } else { + // l.to_string() + // } + // }) + // .collect::>() + // .join("\n"); + self.write_abs(&self.style.write(&s), (0, 0)); + } + + pub fn write_abs_outline(&self, s: &str, pos: (u16, u16)) { + if let Some(parent) = self.parent { + let parent = unsafe { &mut *parent }; + parent.write_abs_outline(s, (self.pos.0 + pos.0, self.pos.1 + pos.1)); + } else { + print!( + "\x1b[{};{}H{}", + self.pos.1 + pos.1 - 1, + self.pos.0 + pos.0 - 1, + self.style.write_outline(s) + ); } + } - if self.style.outline.1 { - print!( - "\x1B[{};{}H{}", - self.pos.1 + 1, - self.pos.0 + 1, - self.style.write_outline(&format!( - "╭{}╮", - "─".repeat(self.get_size_root().0 as usize) - )) - ); - print!( - "\x1B[{};{}H{}", - self.pos.1 + self.written.1 + 2, - self.pos.0 + 1, - self.style.write_outline(&format!( - "╰{}╯", - "─".repeat(self.get_size_root().0 as usize) - )) - ); + pub fn write_abs(&mut self, s: &str, pos: (u16, u16)) { + let width = self.get_size().0 as usize; + let mut max_written = self.written.0; + let mut lines_written = 0; - for i in 0..self.written.1 { + let truncated_lines: Vec<_> = s + .lines() + .map(|l| { + let truncated = if l.len() > width { + l.chars().take(width).collect::() + } else { + l.to_string() + }; + max_written = max_written.max(truncated.len() as u16); + lines_written += 1; + truncated + }) + .collect(); + + self.written.0 = max_written; + self.written.1 += lines_written; + + if let Some(parent) = self.parent { + let parent = unsafe { &mut *parent }; + let combined_pos = (self.pos.0 + pos.0, self.pos.1 + pos.1); + let s_combined = truncated_lines.join("\n"); + parent.write_abs(&s_combined, combined_pos); + } else { + for (i, line) in truncated_lines.iter().enumerate() { print!( - "\x1B[{};{}H{outline_ch}", - self.pos.1 + i + 2, - self.pos.0 + self.get_size_root().0 + 2, + "\x1b[{};{}H{}", + self.pos.1 + pos.1 + i as u16, + self.pos.0 + pos.0, + line ); } } @@ -455,7 +472,7 @@ impl Writer { } pub fn new_frame(&mut self) -> crate::utils::Frame { - crate::utils::Frame::new(self, unsafe { &*self.css }) + crate::utils::Frame::new(self) } pub fn caret(&self) -> String { diff --git a/src/main.rs b/src/main.rs index aabe9dd..5e99f18 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,10 +6,14 @@ fn main() { #[component] pub fn App() { - ersx! { - text { style: style! { - x: 30 px, - y: 4 px - }, "hello, world" } + rsx! { + text { style: style!{ + outline: true, + }, "Hello, World!\nabc" } + + text { style: style!{ + outline: true, + width: 3 px + }, "Hello, World!\nabc testing" } } } diff --git a/src/ui/styles.rs b/src/ui/styles.rs index 02fceaa..35d2ddd 100644 --- a/src/ui/styles.rs +++ b/src/ui/styles.rs @@ -322,7 +322,11 @@ impl Number { } pub fn as_size(&self, written: u16, frame_size: u16, outline: bool) -> u16 { if *self == Number::Auto { - written + if written > 0 { + written - 1 + } else { + written + } } else if outline { self.as_size_raw(frame_size) - 2 } else { diff --git a/src/utils.rs b/src/utils.rs index d77f4f6..ac646d1 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -2,31 +2,27 @@ use std::io::{stdout, Write}; pub struct Frame<'a> { used: Vec, - css: &'a crate::ui::Css, writer: &'a mut crate::Writer, } impl<'a> Frame<'a> { - pub fn new(writer: &'a mut crate::Writer, css: &'a crate::ui::Css) -> Self { + pub fn new(writer: &'a mut crate::Writer) -> Self { Frame { used: vec![0; writer.size.1 as usize], - css, writer, } } pub fn render(&mut self, focused: bool, element: &crate::Element) { let style = element.get_style(); let mut style_element = style.clone().get(focused); + let css = unsafe { &*self.writer.css }; for class in element.get_class().split(" ") { - if let Some(upper) = self - .css - .get(&crate::ui::StyleName::Class(class.to_string())) - { + if let Some(upper) = css.get(&crate::ui::StyleName::Class(class.to_string())) { style_element.merge(upper); } - if let Some(upper) = self.css.get(&crate::ui::StyleName::ClassState( + if let Some(upper) = css.get(&crate::ui::StyleName::ClassState( class.to_string(), if style.2 == "" && focused { "hover".to_string() @@ -56,24 +52,40 @@ impl<'a> Frame<'a> { .x .1 .as_position(style_element.outline.1, y_, self.writer.size.0); - let mut writer = crate::Writer::new( + let mut writer = crate::Writer { focused, - style_element.clone(), - (x, y), - self.writer.size, - self.css, - ); + style: style_element.clone(), + pos: (x, y), + size: self.writer.size, + css, + parent: Some(self.writer), + written: (0, 0), + }; element.render(&mut writer); let (mut width, mut height) = writer.get_size_root(); if style_element.outline.1 { width += 2; height += 2; } - for i in y..y + height { - if let Some(o) = self.used.get_mut(i as usize) { - *o += x + width; + { + let (mut x, mut y) = (x, y); + if style_element.outline.1 { + x -= 1; + y -= 1; + } + let height = if style_element.outline.1 { + height + 1 + } else { + height + }; + + for i in y..y + height { + if let Some(o) = self.used.get_mut(i as usize) { + *o += x + width + 1; + } } } + writer.after_render(width, height); } } }