Merge pull request #8 from osui-rs/writer-rewrite

Writer rewrite
This commit is contained in:
Leo Codes
2024-12-30 12:05:05 +01:00
committed by GitHub
4 changed files with 146 additions and 98 deletions
+86 -62
View File
@@ -117,8 +117,9 @@ pub struct Writer {
style: ui::StyleElement, style: ui::StyleElement,
focused: bool, focused: bool,
size: (u16, u16), size: (u16, u16),
absolute: (u16, u16), pos: (u16, u16),
written: (u16, u16), written: (u16, u16),
parent: Option<*mut Writer>,
} }
pub struct State<T>(Arc<Mutex<T>>); pub struct State<T>(Arc<Mutex<T>>);
@@ -178,9 +179,22 @@ impl Document {
pub fn render(&self) { pub fn render(&self) {
if !self.element.is_null() { if !self.element.is_null() {
let (width, height) = crossterm::terminal::size().unwrap(); let (width, height) = crossterm::terminal::size().unwrap();
let mut frame = utils::Frame::new((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(); utils::clear();
frame.render(true, unsafe { &*self.element }); frame.render(true, unsafe { &*self.element });
writer.after_render(width, height);
utils::flush(); utils::flush();
} }
} }
@@ -345,73 +359,83 @@ impl<T> Handler<T> {
} }
impl Writer { impl Writer {
pub fn new( pub fn after_render(&self, width: u16, height: u16) {
focused: bool, if self.style.outline.1 {
style: ui::StyleElement, let ol = self.style.write_outline("│");
absolute: (u16, u16), let hl = "─".repeat(width as usize - 2);
size: (u16, u16), self.write_abs_outline(&self.style.write_outline(&format!("╭{}╮", hl)), (0, 0));
css: &ui::Css, for i in 1..height {
) -> Writer { self.write_abs_outline(&ol, (0, i));
Writer { self.write_abs_outline(&ol, (width - 1, i));
css, }
style, self.write_abs_outline(&self.style.write_outline(&format!("╰{}╯", hl)), (0, height));
focused,
size,
absolute,
written: (0, 0),
} }
} }
pub fn write(&mut self, s: &str) { pub fn write(&mut self, s: &str) {
let outline_ch = self.style.write_outline("│"); // let width = self.get_size().0 as usize;
for (i, line) in s.lines().enumerate() { // let s = s
if self.style.outline.1 { // .lines()
print!( // .map(|l| {
"\x1B[{};{}H{outline_ch}{}", // if l.len() > width {
self.absolute.1 + 2 + i as u16, // l.chars().take(width).collect::<String>()
self.absolute.0 + 1, // } else {
self.style.write(line), // l.to_string()
); // }
} else { // })
print!( // .collect::<Vec<String>>()
"\x1B[{};{}H{}", // .join("\n");
self.absolute.1 + 1 + i as u16, self.write_abs(&self.style.write(&s), (0, 0));
self.absolute.0 + 1, }
self.style.write(line)
); pub fn write_abs_outline(&self, s: &str, pos: (u16, u16)) {
} if let Some(parent) = self.parent {
let line_len = line.len() as u16; let parent = unsafe { &mut *parent };
if line_len > self.written.0 { parent.write_abs_outline(s, (self.pos.0 + pos.0, self.pos.1 + pos.1));
self.written.0 = line_len; } else {
} print!(
self.written.1 += 1; "\x1b[{};{}H{}",
self.pos.1 + pos.1 - 1,
self.pos.0 + pos.0 - 1,
self.style.write_outline(s)
);
} }
}
if self.style.outline.1 { pub fn write_abs(&mut self, s: &str, pos: (u16, u16)) {
print!( let width = self.get_size().0 as usize;
"\x1B[{};{}H{}", let mut max_written = self.written.0;
self.absolute.1 + 1, let mut lines_written = 0;
self.absolute.0 + 1,
self.style.write_outline(&format!(
"╭{}╮",
"─".repeat(self.get_size_root().0 as usize)
))
);
print!(
"\x1B[{};{}H{}",
self.absolute.1 + self.written.1 + 2,
self.absolute.0 + 1,
self.style.write_outline(&format!(
"╰{}╯",
"─".repeat(self.get_size_root().0 as usize)
))
);
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::<String>()
} 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!( print!(
"\x1B[{};{}H{outline_ch}", "\x1b[{};{}H{}",
self.absolute.1 + i + 2, self.pos.1 + pos.1 + i as u16,
self.absolute.0 + self.get_size_root().0 + 2, self.pos.0 + pos.0,
line
); );
} }
} }
@@ -448,7 +472,7 @@ impl Writer {
} }
pub fn new_frame(&mut self) -> crate::utils::Frame { 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)
} }
pub fn caret(&self) -> String { pub fn caret(&self) -> String {
+8 -7
View File
@@ -7,12 +7,13 @@ fn main() {
#[component] #[component]
pub fn App() { pub fn App() {
rsx! { rsx! {
async { text { style: style!{
sleep(3000); outline: true,
ersx!(text { }, "Hello, World!\nabc" }
"OK"
}) text { style: style!{
} outline: true,
text { "Hello world!" } width: 3 px
}, "Hello, World!\nabc testing" }
} }
} }
+13 -2
View File
@@ -322,14 +322,18 @@ impl Number {
} }
pub fn as_size(&self, written: u16, frame_size: u16, outline: bool) -> u16 { pub fn as_size(&self, written: u16, frame_size: u16, outline: bool) -> u16 {
if *self == Number::Auto { if *self == Number::Auto {
written if written > 0 {
written - 1
} else {
written
}
} else if outline { } else if outline {
self.as_size_raw(frame_size) - 2 self.as_size_raw(frame_size) - 2
} else { } else {
self.as_size_raw(frame_size) 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 { match self {
crate::ui::Number::Px(px) => *px, crate::ui::Number::Px(px) => *px,
crate::ui::Number::Pe(pe) => (frame_size * pe) / 100, crate::ui::Number::Pe(pe) => (frame_size * pe) / 100,
@@ -337,4 +341,11 @@ impl Number {
crate::ui::Number::Auto => *used, 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)
}
}
} }
+39 -27
View File
@@ -1,37 +1,28 @@
use std::io::{stdout, Write}; use std::io::{stdout, Write};
use crate::ui;
pub struct Frame<'a> { pub struct Frame<'a> {
used: Vec<u16>, used: Vec<u16>,
width: u16, writer: &'a mut crate::Writer,
height: u16,
x: u16,
y: u16,
css: &'a ui::Css,
} }
impl<'a> Frame<'a> { 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) -> Self {
Frame { Frame {
used: vec![0; height as usize], used: vec![0; writer.size.1 as usize],
width, writer,
height,
x,
y,
css,
} }
} }
pub fn render(&mut self, focused: bool, element: &crate::Element) { pub fn render(&mut self, focused: bool, element: &crate::Element) {
let style = element.get_style(); let style = element.get_style();
let mut style_element = style.clone().get(focused); let mut style_element = style.clone().get(focused);
let css = unsafe { &*self.writer.css };
for class in element.get_class().split(" ") { for class in element.get_class().split(" ") {
if let Some(upper) = self.css.get(&ui::StyleName::Class(class.to_string())) { if let Some(upper) = css.get(&crate::ui::StyleName::Class(class.to_string())) {
style_element.merge(upper); style_element.merge(upper);
} }
if let Some(upper) = self.css.get(&ui::StyleName::ClassState( if let Some(upper) = css.get(&crate::ui::StyleName::ClassState(
class.to_string(), class.to_string(),
if style.2 == "" && focused { if style.2 == "" && focused {
"hover".to_string() "hover".to_string()
@@ -45,6 +36,7 @@ impl<'a> Frame<'a> {
if style_element.visible.1 { if style_element.visible.1 {
let y = style_element.y.1.as_position( let y = style_element.y.1.as_position(
style_element.outline.1,
&{ &{
let mut y = 0; let mut y = 0;
while y < self.used.len() && self.used[y] != 0 { while y < self.used.len() && self.used[y] != 0 {
@@ -52,28 +44,48 @@ impl<'a> Frame<'a> {
} }
y as u16 y as u16
}, },
self.height, self.writer.size.1,
); );
if let Some(y_) = self.used.get(y as usize) { if let Some(y_) = self.used.get(y as usize) {
let x = style_element.x.1.as_position(y_, self.width); let x =
let mut writer = crate::Writer::new( style_element
.x
.1
.as_position(style_element.outline.1, y_, self.writer.size.0);
let mut writer = crate::Writer {
focused, focused,
style_element.clone(), style: style_element.clone(),
(x + self.x, y + self.y), pos: (x, y),
(self.width, self.height), size: self.writer.size,
self.css, css,
); parent: Some(self.writer),
written: (0, 0),
};
element.render(&mut writer); element.render(&mut writer);
let (mut width, mut height) = writer.get_size_root(); let (mut width, mut height) = writer.get_size_root();
if style_element.outline.1 { if style_element.outline.1 {
width += 2; width += 2;
height += 2; height += 2;
} }
for i in y..y + height { {
if let Some(o) = self.used.get_mut(i as usize) { let (mut x, mut y) = (x, y);
*o += x + width; 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);
} }
} }
} }