From 5820fce49f9350c2c4153cefd7fd2cf80f021b78 Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Wed, 15 Jul 2026 00:39:35 +0200 Subject: [PATCH] Dynamic spaced rows --- pulse-ui/src/layout.rs | 12 +++------ pulse-ui/src/widget/mod.rs | 7 +++++ pulse-ui/src/widget/spaced.rs | 49 +++++++++++++++++++++++++++++++++++ src/main.rs | 24 +++++++---------- 4 files changed, 69 insertions(+), 23 deletions(-) create mode 100644 pulse-ui/src/widget/spaced.rs diff --git a/pulse-ui/src/layout.rs b/pulse-ui/src/layout.rs index cf79b15..4e94d14 100644 --- a/pulse-ui/src/layout.rs +++ b/pulse-ui/src/layout.rs @@ -3,10 +3,7 @@ use crate::unit::{Rect, Size}; #[derive(Debug, Clone)] pub enum LayoutItem { Rows { unit: Size, items: Vec }, - SpacedRows { unit: Size, items: Vec }, - Columns { unit: Size, items: Vec }, - SpacedColumns { unit: Size, items: Vec }, Frame { padding: u16, item: Box }, Widget(Size), @@ -21,10 +18,7 @@ pub struct Allocation { impl LayoutItem { pub fn allocate(&self, alloc: &Rect, full_alloc: &mut Allocation) { match self { - Self::Rows { items, .. } - | Self::Columns { items, .. } - | Self::SpacedRows { items, .. } - | Self::SpacedColumns { items, .. } => { + Self::Rows { items, .. } | Self::Columns { items, .. } => { full_alloc.frame.push(*alloc); let is_row = matches!(self, Self::Rows { .. }); @@ -93,8 +87,8 @@ impl LayoutItem { pub fn get_size<'a>(&'a self) -> &'a Size { match self { - Self::Rows { unit, .. } | Self::SpacedRows { unit, .. } => unit, - Self::Columns { unit, .. } | Self::SpacedColumns { unit, .. } => unit, + Self::Rows { unit, .. } => unit, + Self::Columns { unit, .. } => unit, Self::Widget(unit) => unit, Self::Frame { item, .. } => item.get_size(), } diff --git a/pulse-ui/src/widget/mod.rs b/pulse-ui/src/widget/mod.rs index aa8e40b..819165e 100644 --- a/pulse-ui/src/widget/mod.rs +++ b/pulse-ui/src/widget/mod.rs @@ -1,4 +1,5 @@ pub mod outline; +pub mod spaced; use crate::render::RenderScope; @@ -30,3 +31,9 @@ display_widget!(u64); display_widget!(u128); display_widget!(f32); display_widget!(f64); + +impl Widget for &dyn Widget { + fn render(&self, scope: &mut RenderScope) { + (*self).render(scope); + } +} diff --git a/pulse-ui/src/widget/spaced.rs b/pulse-ui/src/widget/spaced.rs new file mode 100644 index 0000000..e1b336d --- /dev/null +++ b/pulse-ui/src/widget/spaced.rs @@ -0,0 +1,49 @@ +use crate::{layout::LayoutItem, unit::Size::Percent, widget::Widget}; + +pub struct SpacedRows(pub Vec<(LayoutItem, Box)>); + +impl Widget for SpacedRows { + fn render(&self, scope: &mut crate::render::RenderScope) { + let mut alloc = scope.rect.allocate(&crate::layout::LayoutItem::Rows { + unit: Percent(100), + items: self.0.iter().map(|v| v.0.clone()).collect(), + }); + + for i in 0..alloc.widgets.len() { + let item = &self.0[i]; + + if i > 0 { + let rect = &mut alloc.widgets[i]; + scope.draw_text((0, rect.y - 1), "─".repeat(rect.width as usize)); + } + + alloc.draw(i, &*item.1); + } + } +} + +pub struct SpacedColumns(pub Vec<(LayoutItem, Box)>); + +impl Widget for SpacedColumns { + fn render(&self, scope: &mut crate::render::RenderScope) { + let mut alloc = scope.rect.allocate(&crate::layout::LayoutItem::Columns { + unit: Percent(100), + items: self.0.iter().map(|v| v.0.clone()).collect(), + }); + + for i in 0..alloc.widgets.len() { + let item = &self.0[i]; + + if i > 0 { + let rect = &mut alloc.widgets[i]; + + for i in 0..rect.height { + scope.draw_text((rect.x - 1, i), "│"); + } + rect.x += 1; + } + + alloc.draw(i, &*item.1); + } + } +} diff --git a/src/main.rs b/src/main.rs index 0428109..6e51fcb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,7 +5,7 @@ use pulse_ui::{ layout::{LayoutItem, layout}, state::{Refresh, State}, unit::Size, - widget::outline::Outline, + widget::spaced::SpacedRows, }; pub struct PulseTradeApp { @@ -24,22 +24,18 @@ impl App for PulseTradeApp { } async fn layout(&self) -> pulse_ui::layout::LayoutItem { - layout(vec![ - LayoutItem::Frame { - padding: 1, - item: Box::new(LayoutItem::Widget(Size::Flex(1))), - }, - LayoutItem::Frame { - padding: 1, - item: Box::new(LayoutItem::Widget(Size::Flex(1))), - }, - ]) + layout(vec![LayoutItem::Widget(Size::Flex(1))]) } async fn render(&mut self, layout: pulse_ui::layout::Allocation) { - layout.draw(1, format!("{}", self.count.display().await).as_str()); - layout.draw_frame(1, Outline); - layout.draw_frame(2, Outline); + layout.draw( + 0, + SpacedRows(vec![ + (LayoutItem::Widget(Size::Flex(1)), Box::new("one")), + (LayoutItem::Widget(Size::Flex(1)), Box::new("two")), + (LayoutItem::Widget(Size::Flex(1)), Box::new("three")), + ]), + ); } }