Flex components
This commit is contained in:
@@ -10,7 +10,12 @@ fn App(cx: &Arc<Context>) -> View {
|
||||
rsx! {
|
||||
// redraw is important because the effects won't be applied
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
mod flex;
|
||||
|
||||
pub use flex::*;
|
||||
@@ -15,15 +15,15 @@ use access_cell::AccessCell;
|
||||
use crate::{
|
||||
component::EventHandler,
|
||||
engine::{Command, CommandExecutor},
|
||||
render::DrawContext,
|
||||
hooks::{use_effect, HookDependency},
|
||||
View,
|
||||
render::DrawContext,
|
||||
View, ViewWrapper,
|
||||
};
|
||||
|
||||
use super::{scope::Scope, Component, ComponentImpl};
|
||||
|
||||
/// Context represents the runtime state and behavior of a component
|
||||
///
|
||||
///
|
||||
/// Each component instance has a Context that holds:
|
||||
/// - The component implementation
|
||||
/// - The current view (render result)
|
||||
@@ -58,7 +58,7 @@ impl Context {
|
||||
}
|
||||
|
||||
/// Refreshes the component by re-rendering it
|
||||
///
|
||||
///
|
||||
/// Clears event handlers and calls the component to produce a new view.
|
||||
pub fn refresh(self: &Arc<Self>) {
|
||||
self.event_handlers
|
||||
@@ -76,7 +76,7 @@ impl Context {
|
||||
}
|
||||
|
||||
/// Synchronously refreshes the component
|
||||
///
|
||||
///
|
||||
/// Blocks until the component has finished rendering.
|
||||
pub fn refresh_sync(self: &Arc<Self>) {
|
||||
let (tx, rx) = std::sync::mpsc::channel::<()>();
|
||||
@@ -110,7 +110,7 @@ impl Context {
|
||||
}
|
||||
|
||||
/// Registers an event handler for events of type T
|
||||
///
|
||||
///
|
||||
/// When an event of type T is emitted, the handler is called with
|
||||
/// the context and a reference to the event.
|
||||
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
|
||||
///
|
||||
///
|
||||
/// Calls all registered handlers for this event type,
|
||||
/// then propagates the event to child components.
|
||||
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
|
||||
///
|
||||
///
|
||||
/// Similar to emit_event but handlers are called in spawned threads
|
||||
/// for concurrent execution.
|
||||
pub fn emit_event_threaded<E: Any + Send + Sync + Clone + 'static>(
|
||||
@@ -216,6 +216,16 @@ impl Context {
|
||||
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
|
||||
pub fn draw_children(self: &Arc<Self>, ctx: &mut DrawContext) {
|
||||
for scope in self.scopes.lock().unwrap().iter() {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
//! Components are reusable units of UI that can manage their own state
|
||||
//! and respond to events.
|
||||
|
||||
pub mod components;
|
||||
pub mod context;
|
||||
pub mod scope;
|
||||
|
||||
|
||||
@@ -48,6 +48,12 @@ pub mod render;
|
||||
pub mod view_plugins;
|
||||
|
||||
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
|
||||
pub use crate::component::{context::*, scope::*, *};
|
||||
pub use crate::engine::*;
|
||||
|
||||
Reference in New Issue
Block a user