Refactored widget #26

This commit is contained in:
2025-08-04 04:05:38 -05:00
parent 6569a9eb20
commit db1de03fbb
+48 -43
View File
@@ -66,19 +66,22 @@ pub trait Component: Send + Sync {
pub struct WidgetLoad(BoxedElement, HashMap<TypeId, BoxedComponent>); pub struct WidgetLoad(BoxedElement, HashMap<TypeId, BoxedComponent>);
/// A widget with fixed content and no dynamic behavior. /// A widget with fixed content and no dynamic behavior.
pub struct StaticWidget(Mutex<BoxedElement>, Mutex<HashMap<TypeId, BoxedComponent>>); pub struct StaticWidget {
element: Mutex<BoxedElement>,
components: Mutex<HashMap<TypeId, BoxedComponent>>,
}
/// A widget with dynamic content and dependency tracking. /// A widget with dynamic content and dependency tracking.
/// ///
/// This widget supports reactive updates and can be rebuilt using /// This widget supports reactive updates and can be rebuilt using
/// a provided `FnMut()` function when dependencies change. /// a provided `FnMut()` function when dependencies change.
pub struct DynWidget( pub struct DynWidget {
Mutex<BoxedElement>, element: Mutex<BoxedElement>,
Mutex<HashMap<TypeId, BoxedComponent>>, components: Mutex<HashMap<TypeId, BoxedComponent>>,
Mutex<Box<dyn FnMut() -> WidgetLoad + Send + Sync>>, load: Mutex<Box<dyn FnMut() -> WidgetLoad + Send + Sync>>,
Mutex<Vec<Box<dyn DependencyHandler>>>, dependencies: Mutex<Vec<Box<dyn DependencyHandler>>>,
Mutex<Option<Box<dyn FnMut(WidgetLoad) -> WidgetLoad + Send + Sync>>>, injection: Mutex<Option<Box<dyn FnMut(WidgetLoad) -> WidgetLoad + Send + Sync>>>,
); }
/// A reference-counted wrapper around either a static or dynamic widget. /// A reference-counted wrapper around either a static or dynamic widget.
/// ///
@@ -117,18 +120,11 @@ impl WidgetLoad {
impl Widget { impl Widget {
pub fn new_static(e: BoxedElement) -> Self { pub fn new_static(e: BoxedElement) -> Self {
Self::Static(StaticWidget(Mutex::new(e), Mutex::new(HashMap::new()))) Self::Static(StaticWidget::new(e))
} }
pub fn new_dyn<F: FnMut() -> WidgetLoad + 'static + Send + Sync>(mut e: F) -> Self { pub fn new_dyn<F: FnMut() -> WidgetLoad + 'static + Send + Sync>(e: F) -> Self {
let wl = e(); Self::Dynamic(DynWidget::new(e))
Self::Dynamic(DynWidget(
Mutex::new(wl.0),
Mutex::new(wl.1),
Mutex::new(Box::new(e)),
Mutex::new(Vec::new()),
Mutex::new(None),
))
} }
} }
@@ -188,7 +184,7 @@ impl Widget {
} }
Widget::Static(w) => { Widget::Static(w) => {
let wl = WidgetLoad::new(String::new()); let wl = WidgetLoad::new(String::new());
w.1.lock().unwrap().extend(f(wl).1); w.components.lock().unwrap().extend(f(wl).1);
} }
} }
} }
@@ -250,17 +246,20 @@ impl Widget {
impl StaticWidget { impl StaticWidget {
fn after_render(&self) {} fn after_render(&self) {}
fn get_elem(&self) -> MutexGuard<BoxedElement> { fn get_elem(&self) -> MutexGuard<BoxedElement> {
self.0.lock().unwrap() self.element.lock().unwrap()
} }
} }
impl StaticWidget { impl StaticWidget {
pub fn new(e: BoxedElement) -> Self { pub fn new(e: BoxedElement) -> Self {
Self(Mutex::new(e), Mutex::new(HashMap::new())) Self {
element: Mutex::new(e),
components: Mutex::new(HashMap::new()),
}
} }
pub fn component<C: Component + 'static>(&self, c: C) { pub fn component<C: Component + 'static>(&self, c: C) {
self.1 self.components
.lock() .lock()
.unwrap() .unwrap()
.entry(c.type_id()) .entry(c.type_id())
@@ -268,11 +267,14 @@ impl StaticWidget {
} }
pub fn set_component<C: Component + 'static>(&self, c: C) { pub fn set_component<C: Component + 'static>(&self, c: C) {
self.1.lock().unwrap().insert(c.type_id(), Box::new(c)); self.components
.lock()
.unwrap()
.insert(c.type_id(), Box::new(c));
} }
pub fn get<C: Component + 'static + Clone>(&self) -> Option<C> { pub fn get<C: Component + 'static + Clone>(&self) -> Option<C> {
self.1 self.components
.lock() .lock()
.unwrap() .unwrap()
.get(&TypeId::of::<C>()) .get(&TypeId::of::<C>())
@@ -284,43 +286,43 @@ impl StaticWidget {
impl DynWidget { impl DynWidget {
fn after_render(&self) {} fn after_render(&self) {}
fn get_elem(&self) -> MutexGuard<BoxedElement> { fn get_elem(&self) -> MutexGuard<BoxedElement> {
self.0.lock().unwrap() self.element.lock().unwrap()
} }
} }
impl DynWidget { impl DynWidget {
pub fn new<F: FnMut() -> WidgetLoad + 'static + Send + Sync>(mut e: F) -> Self { pub fn new<F: FnMut() -> WidgetLoad + 'static + Send + Sync>(mut e: F) -> Self {
let wl = e(); let wl = e();
Self( Self {
Mutex::new(wl.0), element: Mutex::new(wl.0),
Mutex::new(wl.1), components: Mutex::new(wl.1),
Mutex::new(Box::new(e)), load: Mutex::new(Box::new(e)),
Mutex::new(Vec::new()), dependencies: Mutex::new(Vec::new()),
Mutex::new(None), injection: Mutex::new(None),
) }
} }
/// Replace or modify the widget's structure on reload and init. /// Replace or modify the widget's structure on reload and init.
pub fn inject<F: FnMut(WidgetLoad) -> WidgetLoad + 'static + Send + Sync>(&self, f: F) { pub fn inject<F: FnMut(WidgetLoad) -> WidgetLoad + 'static + Send + Sync>(&self, f: F) {
*self.4.lock().unwrap() = Some(Box::new(f)); *self.injection.lock().unwrap() = Some(Box::new(f));
self.refresh(); self.refresh();
} }
/// Rebuild the widget's content by re-evaluating the original function. /// Rebuild the widget's content by re-evaluating the original function.
pub fn refresh(&self) { pub fn refresh(&self) {
let mut w = (self.2.lock().unwrap())(); let mut w = (self.load.lock().unwrap())();
if let Some(we) = &mut *self.4.lock().unwrap() { if let Some(we) = &mut *self.injection.lock().unwrap() {
w = (we)(w); w = (we)(w);
} }
*self.0.lock().unwrap() = w.0; *self.element.lock().unwrap() = w.0;
*self.1.lock().unwrap() = w.1; *self.components.lock().unwrap() = w.1;
} }
/// Re-evaluates the widget if any dependency has changed. /// Re-evaluates the widget if any dependency has changed.
pub fn auto_refresh(&self) { pub fn auto_refresh(&self) {
for d in self.3.lock().unwrap().iter() { for d in self.dependencies.lock().unwrap().iter() {
if d.check() { if d.check() {
self.refresh(); self.refresh();
} }
@@ -330,17 +332,17 @@ impl DynWidget {
/// Adds a dependency to this widget. /// Adds a dependency to this widget.
pub fn dependency<D: DependencyHandler + 'static>(&self, d: D) { pub fn dependency<D: DependencyHandler + 'static>(&self, d: D) {
d.add(); d.add();
self.3.lock().unwrap().push(Box::new(d)); self.dependencies.lock().unwrap().push(Box::new(d));
} }
/// Adds a boxed dependency. /// Adds a boxed dependency.
pub fn dependency_box(&self, d: Box<dyn DependencyHandler>) { pub fn dependency_box(&self, d: Box<dyn DependencyHandler>) {
d.add(); d.add();
self.3.lock().unwrap().push(d); self.dependencies.lock().unwrap().push(d);
} }
pub fn component<C: Component + 'static>(&self, c: C) { pub fn component<C: Component + 'static>(&self, c: C) {
self.1 self.components
.lock() .lock()
.unwrap() .unwrap()
.entry(c.type_id()) .entry(c.type_id())
@@ -348,11 +350,14 @@ impl DynWidget {
} }
pub fn set_component<C: Component + 'static>(&self, c: C) { pub fn set_component<C: Component + 'static>(&self, c: C) {
self.1.lock().unwrap().insert(c.type_id(), Box::new(c)); self.components
.lock()
.unwrap()
.insert(c.type_id(), Box::new(c));
} }
pub fn get<C: Component + 'static + Clone>(&self) -> Option<C> { pub fn get<C: Component + 'static + Clone>(&self) -> Option<C> {
self.1 self.components
.lock() .lock()
.unwrap() .unwrap()
.get(&TypeId::of::<C>()) .get(&TypeId::of::<C>())