Flex components

This commit is contained in:
2026-02-01 18:20:20 +01:00
parent 76984187a0
commit 25bebcbb81
6 changed files with 85 additions and 9 deletions
+6 -1
View File
@@ -10,7 +10,12 @@ fn App(cx: &Arc<Context>) -> View {
rsx! { rsx! {
// redraw is important because the effects won't be applied // redraw is important because the effects won't be applied
impl size_auto, center, redraw impl size_auto, center, redraw
Card { content: "Hello World".to_string() } FlexRow {
impl size_auto, redraw
Card { content: "One".to_string() }
impl size_auto, redraw
Card { content: "Two".to_string() }
}
} }
.view(&cx) .view(&cx)
} }
+51
View File
@@ -0,0 +1,51 @@
use crate::component_prelude::*;
#[component]
pub fn FlexRow(cx: &Arc<Context>, children: Rsx) -> View {
children.generate_children(&cx);
Arc::new({
let cx = cx.clone();
move |ctx| {
for (child, view_wrapper) in cx.get_children() {
let view = child.get_view();
if let Some(view_wrapper) = view_wrapper {
let mut ctx2 = ctx.clone();
view_wrapper(&mut ctx2, view);
ctx.drawing.append(&mut ctx2.drawing);
ctx.area.y += ctx2.allocated.height;
} else {
ctx.draw_view(ctx.area.clone(), view);
}
}
}
})
}
#[component]
pub fn FlexColumn(cx: &Arc<Context>, children: Rsx) -> View {
children.generate_children(&cx);
Arc::new({
let cx = cx.clone();
move |ctx| {
for (child, view_wrapper) in cx.get_children() {
let view = child.get_view();
if let Some(view_wrapper) = view_wrapper {
let mut ctx2 = ctx.clone();
view_wrapper(&mut ctx2, view);
ctx.drawing.append(&mut ctx2.drawing);
ctx.area.x += ctx2.allocated.width;
} else {
ctx.draw_view(ctx.area.clone(), view);
}
}
}
})
}
+3
View File
@@ -0,0 +1,3 @@
mod flex;
pub use flex::*;
+18 -8
View File
@@ -15,15 +15,15 @@ use access_cell::AccessCell;
use crate::{ use crate::{
component::EventHandler, component::EventHandler,
engine::{Command, CommandExecutor}, engine::{Command, CommandExecutor},
render::DrawContext,
hooks::{use_effect, HookDependency}, hooks::{use_effect, HookDependency},
View, render::DrawContext,
View, ViewWrapper,
}; };
use super::{scope::Scope, Component, ComponentImpl}; use super::{scope::Scope, Component, ComponentImpl};
/// Context represents the runtime state and behavior of a component /// Context represents the runtime state and behavior of a component
/// ///
/// Each component instance has a Context that holds: /// Each component instance has a Context that holds:
/// - The component implementation /// - The component implementation
/// - The current view (render result) /// - The current view (render result)
@@ -58,7 +58,7 @@ impl Context {
} }
/// Refreshes the component by re-rendering it /// Refreshes the component by re-rendering it
/// ///
/// Clears event handlers and calls the component to produce a new view. /// Clears event handlers and calls the component to produce a new view.
pub fn refresh(self: &Arc<Self>) { pub fn refresh(self: &Arc<Self>) {
self.event_handlers self.event_handlers
@@ -76,7 +76,7 @@ impl Context {
} }
/// Synchronously refreshes the component /// Synchronously refreshes the component
/// ///
/// Blocks until the component has finished rendering. /// Blocks until the component has finished rendering.
pub fn refresh_sync(self: &Arc<Self>) { pub fn refresh_sync(self: &Arc<Self>) {
let (tx, rx) = std::sync::mpsc::channel::<()>(); let (tx, rx) = std::sync::mpsc::channel::<()>();
@@ -110,7 +110,7 @@ impl Context {
} }
/// Registers an event handler for events of type T /// Registers an event handler for events of type T
/// ///
/// When an event of type T is emitted, the handler is called with /// When an event of type T is emitted, the handler is called with
/// the context and a reference to the event. /// the context and a reference to the event.
pub fn on_event<T: Any + 'static, F: Fn(&Arc<Self>, &T) + Send + Sync + 'static>( pub fn on_event<T: Any + 'static, F: Fn(&Arc<Self>, &T) + Send + Sync + 'static>(
@@ -132,7 +132,7 @@ impl Context {
} }
/// Emits an event to this component and all descendants /// Emits an event to this component and all descendants
/// ///
/// Calls all registered handlers for this event type, /// Calls all registered handlers for this event type,
/// then propagates the event to child components. /// then propagates the event to child components.
pub fn emit_event<E: Send + Sync + Any + 'static>(self: &Arc<Self>, event: E) { pub fn emit_event<E: Send + Sync + Any + 'static>(self: &Arc<Self>, event: E) {
@@ -153,7 +153,7 @@ impl Context {
} }
/// Emits an event to this component in a spawned thread /// Emits an event to this component in a spawned thread
/// ///
/// Similar to emit_event but handlers are called in spawned threads /// Similar to emit_event but handlers are called in spawned threads
/// for concurrent execution. /// for concurrent execution.
pub fn emit_event_threaded<E: Any + Send + Sync + Clone + 'static>( pub fn emit_event_threaded<E: Any + Send + Sync + Clone + 'static>(
@@ -216,6 +216,16 @@ impl Context {
self.scopes.lock().unwrap().push(scope); self.scopes.lock().unwrap().push(scope);
} }
/// Gets the children
pub fn get_children(self: &Arc<Self>) -> Vec<(Arc<Context>, Option<ViewWrapper>)> {
self.scopes
.lock()
.unwrap()
.iter()
.flat_map(|s| s.children.lock().unwrap().clone())
.collect::<Vec<_>>()
}
/// Renders all child components to the draw context /// Renders all child components to the draw context
pub fn draw_children(self: &Arc<Self>, ctx: &mut DrawContext) { pub fn draw_children(self: &Arc<Self>, ctx: &mut DrawContext) {
for scope in self.scopes.lock().unwrap().iter() { for scope in self.scopes.lock().unwrap().iter() {
+1
View File
@@ -4,6 +4,7 @@
//! Components are reusable units of UI that can manage their own state //! Components are reusable units of UI that can manage their own state
//! and respond to events. //! and respond to events.
pub mod components;
pub mod context; pub mod context;
pub mod scope; pub mod scope;
+6
View File
@@ -48,6 +48,12 @@ pub mod render;
pub mod view_plugins; pub mod view_plugins;
pub mod prelude { pub mod prelude {
//! Prelude module - Re-exports commonly used items for convenience
pub use crate::component::components::*;
pub use crate::component_prelude::*;
}
pub mod component_prelude {
//! Prelude module - Re-exports commonly used items for convenience //! Prelude module - Re-exports commonly used items for convenience
pub use crate::component::{context::*, scope::*, *}; pub use crate::component::{context::*, scope::*, *};
pub use crate::engine::*; pub use crate::engine::*;