Merge pull request #21 from osui-rs/rsx-patch-args

Rsx patch args
This commit is contained in:
Leo Codes
2025-08-02 12:59:23 -05:00
committed by GitHub
8 changed files with 94 additions and 27 deletions
+1
View File
@@ -25,6 +25,7 @@ cc = "1.0"
[dependencies] [dependencies]
crossterm = "0.28.1" crossterm = "0.28.1"
figlet-rs = "0.1.5"
[profile.dev] [profile.dev]
opt-level = 1 opt-level = 1
+7 -6
View File
@@ -19,8 +19,9 @@ pub fn app(screen: Arc<Screen>) -> Rsx {
move |_, _: &crossterm::event::Event| { move |_, _: &crossterm::event::Event| {
screen.close(); screen.close();
}}); }});
FlexRow { FlexRow, gap: 1, {
FlexCol { FlexCol, gap: 3, {
Heading, smooth: false, { "OSUI" }
@Transform::new().padding(2, 2); @Transform::new().padding(2, 2);
@Style { foreground: None, background: Background::RoundedOutline(0x00ff00) }; @Style { foreground: None, background: Background::RoundedOutline(0x00ff00) };
Div { Div {
@@ -34,14 +35,14 @@ pub fn app(screen: Arc<Screen>) -> Rsx {
} }
// TODO: div with width full // TODO: div with width full
} (1) }
FlexCol { FlexCol {
Div { static Div { // static only affects the element, not children
%count %count
"This will increment every second: {count}" "This will increment every second: {count}"
} }
} (2) }
} (0) }
} }
} }
+6 -6
View File
@@ -6,33 +6,33 @@ use crate::{
}; };
pub struct FlexRow { pub struct FlexRow {
gap: u16, pub gap: u16,
children: Mutex<Vec<Arc<Widget>>>, children: Mutex<Vec<Arc<Widget>>>,
size: (u16, u16), size: (u16, u16),
} }
pub struct FlexCol { pub struct FlexCol {
gap: u16, pub gap: u16,
children: Mutex<Vec<Arc<Widget>>>, children: Mutex<Vec<Arc<Widget>>>,
size: (u16, u16), size: (u16, u16),
} }
impl FlexRow { impl FlexRow {
pub fn new(gap: u16) -> Self { pub fn new() -> Self {
Self { Self {
children: Mutex::new(Vec::new()), children: Mutex::new(Vec::new()),
size: (0, 0), size: (0, 0),
gap, gap: 0,
} }
} }
} }
impl FlexCol { impl FlexCol {
pub fn new(gap: u16) -> Self { pub fn new() -> Self {
Self { Self {
children: Mutex::new(Vec::new()), children: Mutex::new(Vec::new()),
size: (0, 0), size: (0, 0),
gap, gap: 0,
} }
} }
} }
+55
View File
@@ -0,0 +1,55 @@
use std::sync::{Arc, Mutex};
use figlet_rs::FIGfont;
use crate::{
widget::{Element, Widget},
NoRender,
};
pub struct Heading {
pub font: FIGfont,
pub smooth: bool,
children: Mutex<Vec<Arc<Widget>>>,
}
impl Heading {
pub fn new() -> Heading {
Heading {
font: FIGfont::standard().unwrap(),
smooth: false,
children: Mutex::new(Vec::new()),
}
}
}
impl Element for Heading {
fn render(&mut self, scope: &mut crate::prelude::RenderScope) {
let mut s = String::new();
for element in self.children.lock().unwrap().iter() {
if let Some(e) = element.get_elem().as_any().downcast_ref::<String>() {
s += e;
}
}
if let Some(t) = self.font.convert(&s) {
scope.draw_text(&if self.smooth {
format!("{t}").replace("-", "─").replace("|", "│")
} else {
format!("{t}")
});
}
}
fn draw_child(&self, element: &Arc<Widget>) {
element.inject(|w| w.component(NoRender));
self.children.lock().unwrap().push(element.clone());
}
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
}
+2
View File
@@ -1,8 +1,10 @@
pub mod div; pub mod div;
pub mod flex; pub mod flex;
pub mod heading;
pub use div::*; pub use div::*;
pub use flex::*; pub use flex::*;
pub use heading::*;
use crate::Element; use crate::Element;
+3 -5
View File
@@ -46,13 +46,11 @@ impl Rsx {
for rsx_elem in self.0 { for rsx_elem in self.0 {
match rsx_elem { match rsx_elem {
RsxElement::DynElement(f, dep, child) => { RsxElement::DynElement(f, dep, child) => {
let w = if let Some(parent) = &parent {
let w = screen.draw_box_dyn(f); let w = screen.draw_box_dyn(f);
if let Some(parent) = &parent {
parent.get_elem().draw_child(&w); parent.get_elem().draw_child(&w);
w }
} else {
screen.draw_box_dyn(f)
};
for d in dep { for d in dep {
w.dependency_box(d); w.dependency_box(d);
+14 -7
View File
@@ -256,24 +256,31 @@ macro_rules! rsx_inner {
}; };
// static // static
($r:expr, $(@$comp:expr;)* static $name:path { $($inner:tt)* } ($($e:expr),*) $($rest:tt)*) => { ($r:expr, $(@$comp:expr;)* static $name:path, $($f:ident $(: $v:expr)?),+, { $($inner:tt)* } $($rest:tt)*) => {
let w = $crate::widget::StaticWidget::new(Box::new(<$name>::new($($e),*))); let w = $crate::widget::StaticWidget::new(Box::new({
let mut elem = <$name>::new();
$(elem.$f = $($v)?;)+
elem
}));
$(w.component($comp);)* $(w.component($comp);)*
$r.create_element_static(w, $crate::frontend::Rsx(Vec::new())); $r.create_element_static(w, $crate::rsx!{ $($inner)* });
$crate::rsx_inner! { $r, $($rest)* }; $crate::rsx_inner! { $r, $($rest)* };
}; };
// static
($r:expr, $(@$comp:expr;)* static $name:path { $($inner:tt)* } $($rest:tt)*) => { ($r:expr, $(@$comp:expr;)* static $name:path { $($inner:tt)* } $($rest:tt)*) => {
let w = $crate::widget::StaticWidget::new(Box::new(<$name>::new())); let w = $crate::widget::StaticWidget::new(Box::new(<$name>::new()));
$(w.component($comp);)* $(w.component($comp);)*
$r.create_element_static(w, $crate::frontend::Rsx(Vec::new())); $r.create_element_static(w, $crate::rsx!{ $($inner)* });
$crate::rsx_inner! { $r, $($rest)* }; $crate::rsx_inner! { $r, $($rest)* };
}; };
($r:expr, $(@$comp:expr;)* $(%$dep:ident)* $name:path { $($inner:tt)* } ($($e:expr),*) $($rest:tt)*) => { ($r:expr, $(@$comp:expr;)* $(%$dep:ident)* $name:path, $($f:ident $(: $v:expr)?),+, { $($inner:tt)* } $($rest:tt)*) => {
$r.create_element({ $(let $dep = $dep.clone();)* move || { $r.create_element({ $(let $dep = $dep.clone();)* move || {
$crate::widget::WidgetLoad::new(<$name>::new($($e),*)) $(.component($comp))* $crate::widget::WidgetLoad::new({
let mut elem = <$name>::new();
$(elem.$f = $($v)?;)+
elem
}) $(.component($comp))*
} }, vec![$(Box::new($dep.clone())),*], $crate::rsx!{ $($inner)* }); } }, vec![$(Box::new($dep.clone())),*], $crate::rsx!{ $($inner)* });
$crate::rsx_inner! { $r, $($rest)* }; $crate::rsx_inner! { $r, $($rest)* };
}; };
+5 -2
View File
@@ -173,13 +173,16 @@ impl Widget {
pub fn inject<F: FnMut(WidgetLoad) -> WidgetLoad + 'static + Send + Sync>( pub fn inject<F: FnMut(WidgetLoad) -> WidgetLoad + 'static + Send + Sync>(
self: &Arc<Self>, self: &Arc<Self>,
f: F, mut f: F,
) { ) {
match &**self { match &**self {
Widget::Dynamic(w) => { Widget::Dynamic(w) => {
w.inject(f); w.inject(f);
} }
Widget::Static(_) => {} Widget::Static(w) => {
let wl = WidgetLoad::new(String::new());
w.1.lock().unwrap().extend(f(wl).1);
}
} }
} }