Refactored widget #26
This commit is contained in:
+48
-43
@@ -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>())
|
||||||
|
|||||||
Reference in New Issue
Block a user